-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor: Modify udp_recvfrom. Raplace recvmsg with WSARecvMsg in windows #1324
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -93,7 +93,8 @@ static int udp_create_server_socket(server_type *server, const char *ifname, con | |
if (addr_bind(udp_fd, server_addr, 1, 1, UDP_SOCKET) < 0) | ||
return -1; | ||
|
||
socket_set_nonblocking(udp_fd); | ||
if (evutil_make_socket_nonblocking(udp_fd)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. braces please |
||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Set socket nonblocking fail\n"); | ||
|
||
struct event *udp_ev = | ||
event_new(server->event_base, udp_fd, EV_READ | EV_PERSIST, udp_server_input_handler, server_addr); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -467,28 +467,22 @@ static int create_new_connected_udp_socket(dtls_listener_relay_server_type *serv | |
|
||
evutil_socket_t udp_fd = socket(s->local_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check that |
||
if (udp_fd < 0) { | ||
perror("socket"); | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket\n", __FUNCTION__); | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Create socket fail: %d\n", socket_errno()); | ||
return -1; | ||
} | ||
|
||
if (sock_bind_to_device(udp_fd, (unsigned char *)(s->e->relay_ifname)) < 0) { | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind udp server socket to device %s\n", (char *)(s->e->relay_ifname)); | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind udp server socket to device[%d]: %s\n", socket_errno(), | ||
(char *)(s->e->relay_ifname)); | ||
} | ||
|
||
ioa_socket_handle ret = (ioa_socket *)malloc(sizeof(ioa_socket)); | ||
ioa_socket_handle ret = create_ioa_socket_from_fd(NULL, udp_fd, NULL, s->st, CLIENT_SOCKET, NULL, NULL); | ||
if (!ret) { | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket structure\n", __FUNCTION__); | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot allocate new ioa_socket\n"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it would be nice to continue log the function name, as well as the file and line number. Additionally, can the error code explaining the allocation failure be logged? |
||
socket_closesocket(udp_fd); | ||
return -1; | ||
} | ||
|
||
memset(ret, 0, sizeof(ioa_socket)); | ||
|
||
ret->magic = SOCKET_MAGIC; | ||
|
||
ret->fd = udp_fd; | ||
|
||
ret->family = s->family; | ||
ret->st = s->st; | ||
ret->sat = CLIENT_SOCKET; | ||
|
@@ -627,7 +621,7 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void *arg) | |
#else | ||
int flags = MSG_DONTWAIT; | ||
#endif | ||
bsize = udp_recvfrom(fd, &(server->sm.m.sm.nd.src_addr), &(server->addr), (char *)ioa_network_buffer_data(elem), | ||
bsize = udp_recvfrom(s, &(server->sm.m.sm.nd.src_addr), &(server->addr), (char *)ioa_network_buffer_data(elem), | ||
(int)ioa_network_buffer_get_capacity_udp(), &(server->sm.m.sm.nd.recv_ttl), | ||
&(server->sm.m.sm.nd.recv_tos), server->e->cmsg, flags, NULL); | ||
|
||
|
@@ -664,7 +658,7 @@ static void udp_server_input_handler(evutil_socket_t fd, short what, void *arg) | |
int ttl = 0; | ||
int tos = 0; | ||
int slen = server->slen0; | ||
udp_recvfrom(fd, &orig_addr, &(server->addr), buffer, (int)sizeof(buffer), &ttl, &tos, server->e->cmsg, eflags, | ||
udp_recvfrom(s, &orig_addr, &(server->addr), buffer, (int)sizeof(buffer), &ttl, &tos, server->e->cmsg, eflags, | ||
&errcode); | ||
// try again... | ||
do { | ||
|
@@ -789,6 +783,9 @@ static int create_server_socket(dtls_listener_relay_server_type *server, int rep | |
} | ||
} | ||
|
||
if (evutil_make_socket_nonblocking(udp_listen_fd)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. braces please |
||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Set nonblocking fail\n"); | ||
|
||
server->udp_listen_ev = | ||
event_new(server->e->event_base, udp_listen_fd, EV_READ | EV_PERSIST, udp_server_input_handler, server); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -786,7 +786,8 @@ int set_socket_options_fd(evutil_socket_t fd, SOCKET_TYPE st, int family) { | |
} | ||
} | ||
|
||
socket_set_nonblocking(fd); | ||
if (evutil_make_socket_nonblocking(fd)) | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Set socket nonblocking fail\n"); | ||
|
||
if (!is_stream_socket(st)) { | ||
set_raw_socket_ttl_options(fd, family); | ||
|
@@ -884,11 +885,12 @@ ioa_socket_handle create_unbound_relay_ioa_socket(ioa_engine_handle e, int famil | |
return NULL; | ||
} | ||
|
||
ret = (ioa_socket *)calloc(sizeof(ioa_socket), 1); | ||
|
||
ret->magic = SOCKET_MAGIC; | ||
ret = create_ioa_socket_from_fd(e, fd, NULL, st, sat, NULL, NULL); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. declare and define on same line |
||
if (!ret) { | ||
socket_closesocket(fd); | ||
return NULL; | ||
} | ||
|
||
ret->fd = fd; | ||
ret->family = family; | ||
ret->st = st; | ||
ret->sat = sat; | ||
|
@@ -1294,10 +1296,28 @@ ioa_socket_handle create_ioa_socket_from_fd(ioa_engine_handle e, ioa_socket_raw | |
} | ||
|
||
ret = (ioa_socket *)calloc(sizeof(ioa_socket), 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. declare and define on same line |
||
if (!ret) { | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot allocate new ioa_socket structure\n"); | ||
return NULL; | ||
} | ||
|
||
ret->magic = SOCKET_MAGIC; | ||
|
||
ret->fd = fd; | ||
|
||
#if defined(_MSC_VER) | ||
|
||
DWORD dwBytesRecvd = 0; | ||
GUID guidWSARecvMsg = WSAID_WSARECVMSG; | ||
int nRet = WSAIoctl(fd, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidWSARecvMsg, sizeof(guidWSARecvMsg), &ret->recvmsg, | ||
sizeof(LPFN_WSARECVMSG), &dwBytesRecvd, NULL, NULL); | ||
if (nRet) | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "WSAIoctl fail:%d\n", socket_errno()); | ||
else if (!ret->recvmsg) | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "ret->recvmsg is null\n"); | ||
|
||
#endif | ||
|
||
ret->st = st; | ||
ret->sat = sat; | ||
ret->e = e; | ||
|
@@ -1933,11 +1953,15 @@ static int socket_readerr(evutil_socket_t fd, ioa_addr *orig_addr) { | |
typedef unsigned char recv_ttl_t; | ||
typedef unsigned char recv_tos_t; | ||
|
||
int udp_recvfrom(evutil_socket_t fd, ioa_addr *orig_addr, const ioa_addr *like_addr, char *buffer, int buf_size, | ||
int udp_recvfrom(ioa_socket_handle s, ioa_addr *orig_addr, const ioa_addr *like_addr, char *buffer, int buf_size, | ||
int *ttl, int *tos, char *ecmsg, int flags, uint32_t *errcode) { | ||
int len = 0; | ||
|
||
if (fd < 0 || !orig_addr || !like_addr || !buffer) | ||
if (!s || !orig_addr || !like_addr || !buffer) | ||
return -1; | ||
|
||
evutil_socket_t fd = s->fd; | ||
if (fd < 0) | ||
return -1; | ||
|
||
if (errcode) | ||
|
@@ -1947,13 +1971,122 @@ int udp_recvfrom(evutil_socket_t fd, ioa_addr *orig_addr, const ioa_addr *like_a | |
recv_ttl_t recv_ttl = TTL_DEFAULT; | ||
recv_tos_t recv_tos = TOS_DEFAULT; | ||
|
||
#if defined(_MSC_VER) || !defined(CMSG_SPACE) | ||
#if defined(_MSC_VER) | ||
|
||
DWORD bytes_received = 0; | ||
WSAMSG msg = {0}; | ||
WSABUF sbuf = {0}; | ||
uint8_t cmdbuf[512]; | ||
WSACMSGHDR *cmsg; | ||
PIN6_PKTINFO pi; | ||
|
||
sbuf.buf = (char FAR *)buffer; | ||
sbuf.len = (u_long)buf_size; | ||
msg.lpBuffers = &sbuf; | ||
msg.dwBufferCount = 1; | ||
msg.name = (LPSOCKADDR)orig_addr; | ||
msg.namelen = slen; | ||
msg.Control.buf = (char FAR *)cmdbuf; | ||
msg.Control.len = (u_long)sizeof(cmdbuf); | ||
|
||
if (!s->recvmsg) { | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, | ||
"WSARecvMsg is null. use recvfrom. the ttl and tos is not got. So set it to the default value\n"); | ||
len = recvfrom(fd, buffer, buf_size, flags, (struct sockaddr *)orig_addr, (socklen_t *)&slen); | ||
if (len < 0 && errcode) { | ||
*errcode = (uint32_t)socket_errno(); | ||
return -1; | ||
} | ||
return len; | ||
} | ||
|
||
int nRet = 0; | ||
/* Receive a packet */ | ||
nRet = (s->recvmsg)(s->fd, &msg, &bytes_received, NULL, NULL); | ||
if (nRet) { | ||
if (s->e->verbose && socket_ewouldblock() == socket_errno()) | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_WARNING, "WSARecvMsg fail:%d\n", socket_errno()); | ||
else | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "WSARecvMsg fail:%d\n", socket_errno()); | ||
if (errcode) | ||
*errcode = (uint32_t)socket_errno(); | ||
return -1; | ||
} | ||
|
||
/* Parse the header info, look for the local address */ | ||
cmsg = WSA_CMSG_FIRSTHDR(&msg); | ||
for (; cmsg != NULL; cmsg = WSA_CMSG_NXTHDR(&msg, cmsg)) { | ||
// TURN_LOG_FUNC(TURN_LOG_LEVEL_DEBUG, "level: %d; type:%d\n", cmsg->cmsg_level, cmsg->cmsg_type); | ||
switch (cmsg->cmsg_level) { | ||
case IPPROTO_IP: | ||
switch (cmsg->cmsg_type) { | ||
#if defined(IP_RECVTTL) && !defined(__sparc_v9__) | ||
case IP_RECVTTL: | ||
case IP_TTL: | ||
recv_ttl = *((recv_ttl_t *)WSA_CMSG_DATA(cmsg)); | ||
break; | ||
#endif | ||
#if defined(IP_RECVTOS) | ||
case IP_RECVTOS: | ||
case IP_TOS: | ||
recv_tos = *((recv_tos_t *)WSA_CMSG_DATA(cmsg)); | ||
break; | ||
#endif | ||
#if defined(IP_RECVERR) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what would cause these various defines to be defined or not defined? Having some documentation in the code explaining that would be helpful. |
||
case IP_RECVERR: { | ||
struct turn_sock_extended_err *e = (struct turn_sock_extended_err *)WSA_CMSG_DATA(cmsg); | ||
if (errcode) | ||
*errcode = e->ee_errno; | ||
} break; | ||
#endif | ||
default:; | ||
/* no break */ | ||
}; | ||
break; | ||
case IPPROTO_IPV6: | ||
switch (cmsg->cmsg_type) { | ||
#if defined(IPV6_RECVHOPLIMIT) && !defined(__sparc_v9__) | ||
case IPV6_RECVHOPLIMIT: | ||
case IPV6_HOPLIMIT: | ||
recv_ttl = *((recv_ttl_t *)CMSG_DATA(cmsg)); | ||
break; | ||
#endif | ||
#if defined(IPV6_RECVTCLASS) | ||
case IPV6_RECVTCLASS: | ||
case IPV6_TCLASS: | ||
recv_tos = *((recv_tos_t *)WSA_CMSG_DATA(cmsg)); | ||
break; | ||
#endif | ||
#if defined(IPV6_RECVERR) | ||
case IPV6_RECVERR: { | ||
struct turn_sock_extended_err *e = (struct turn_sock_extended_err *)WSA_CMSG_DATA(cmsg); | ||
if (errcode) | ||
*errcode = e->ee_errno; | ||
} break; | ||
#endif | ||
default:; | ||
/* no break */ | ||
}; | ||
break; | ||
default:; | ||
/* no break */ | ||
}; | ||
} | ||
|
||
len = bytes_received; | ||
|
||
if (s->e->verbose) | ||
TURN_LOG_FUNC(TURN_LOG_LEVEL_DEBUG, "WSARecvMsg len: %d; ttl: %08X; tos: %08X\n", bytes_received, recv_ttl, | ||
recv_tos); | ||
|
||
#elif !defined(CMSG_SPACE) | ||
do { | ||
len = recvfrom(fd, buffer, buf_size, flags, (struct sockaddr *)orig_addr, (socklen_t *)&slen); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what prevents this from looping forever? |
||
} while (len < 0 && socket_eintr()); | ||
if (len < 0 && errcode) | ||
*errcode = (uint32_t)socket_errno(); | ||
*errcode = (uint32_t)errno; | ||
#else | ||
|
||
struct msghdr msg; | ||
struct iovec iov; | ||
|
||
|
@@ -1977,7 +2110,7 @@ int udp_recvfrom(evutil_socket_t fd, ioa_addr *orig_addr, const ioa_addr *like_a | |
#endif | ||
|
||
do { | ||
len = recvmsg(fd, &msg, flags); | ||
len = recvmsg(s->fd, &msg, flags); | ||
} while (len < 0 && socket_eintr()); | ||
|
||
#if defined(MSG_ERRQUEUE) | ||
|
@@ -1991,7 +2124,7 @@ int udp_recvfrom(evutil_socket_t fd, ioa_addr *orig_addr, const ioa_addr *like_a | |
// Linux | ||
int eflags = MSG_ERRQUEUE | MSG_DONTWAIT; | ||
uint32_t errcode1 = 0; | ||
udp_recvfrom(fd, orig_addr, like_addr, buffer, buf_size, ttl, tos, ecmsg, eflags, &errcode1); | ||
udp_recvfrom(s, orig_addr, like_addr, buffer, buf_size, ttl, tos, ecmsg, eflags, &errcode1); | ||
// try again... | ||
do { | ||
len = recvmsg(fd, &msg, flags); | ||
|
@@ -2507,8 +2640,8 @@ static int socket_input_worker(ioa_socket_handle s) { | |
if (len == 0) | ||
len = -1; | ||
} else if (s->fd >= 0) { /* UDP and DTLS */ | ||
ret = udp_recvfrom(s->fd, &remote_addr, &(s->local_addr), (char *)(buf_elem->buf.buf), UDP_STUN_BUFFER_SIZE, &ttl, | ||
&tos, s->e->cmsg, 0, NULL); | ||
ret = udp_recvfrom(s, &remote_addr, &(s->local_addr), (char *)(buf_elem->buf.buf), UDP_STUN_BUFFER_SIZE, &ttl, &tos, | ||
s->e->cmsg, 0, NULL); | ||
len = ret; | ||
if (s->ssl && (len > 0)) { /* DTLS */ | ||
send_ssl_backlog_buffers(s); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be checking defined(WINDOWS) like is done in other places?