Binding to a UDP socket for IOCP using C - c

I am trying to read from a UDP port, from a local (loopback) application, using IOCP. IOCP works fine for TCP/IP, but I am unable to open the socket properly for UDP.
This is what I am doing:
// same as for tcp/ip
struct sockaddr_in remoteAddr = { 0 };
remoteAddr.sin_addr.s_addr = LOOPBACK_ADDRESS;
remoteAddr.sin_family = AF_INET;
remoteAddr.sin_port = htons(portNumber);
// using SOCK_DGRAM here
SOCKET sock = INVALID_SOCKET;
sock = WSASocketW(AF_INET, SOCK_DGRAM, IPPROTO_IP,
NULL, 0, WSA_FLAG_OVERLAPPED);
if( sock == INVALID_SOCKET ) {
LOG("WSASocketW failed: %d", WSAGetLastError());
return;
}
nRet = WSAConnect(*sock, (const struct sockaddr*)&remoteAddr, sizeof(remoteAddr),
NULL, NULL, NULL, NULL);
if (nRet == SOCKET_ERROR)
{
LOG("WSAConnect failed: %d", WSAGetLastError());
return;
}
nRet = WSARecv(sock, &wsabuf, 1, NULL, &flags, &overlapped, NULL);
if (nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()))
{
LOG("WSARecv failed: %d", WSAGetLastError());
return;
}
// no errors of any kind
LOG("seems good so far");
Everything passes without errors, but GetQueuedCompletionStatus inside the worker loop thread never returns. If I do the same thing to connect to a TCP socket (just replace SOCK_DGRAM with SOCK_STREAM basically), I get data inside the loop.
Am I doing something obviously wrong?
(Btw) I know I could use WSARecvFrom, but I would like to reuse as much code as possible from the TCP socket. I.e. hopefully, set everything up and then post WSARecv calls inside the worker thread regardless of the type of the socket (WSARecv is supposed to work with UDP properly, AFAIK).

Managed to get it to work, thanks to the comment by #WouterHuysentruit.
Basically, if I want to receive UDP packets using WSARecv, I need to bind. If I want to send UDP packets using WSASend, I need to connect. So the following works:
if (port_type == incoming_packets)
{
// bind to port
ret = bind(*sock, (const struct sockaddr*)&remoteAddr, sizeof(remoteAddr));
...
WSARecv(...);
}
else
{
// this can send to a loopback udp port which is bound in
// a different application
ret = WSAConnect(*sock, (const struct sockaddr*)&remoteAddr, sizeof(remoteAddr), ...);
...
WSASend(...);
}
As others have pointed out, WSAReceiveFrom/WSASendTo are usually a better choice for UDP, but in this case I can support multiple port types using IOCP transparently.

Related

AF_UNIX socket behaviour on client side before the server calls accept()

I am writing some code to abstract AF_UNIX client-server comms away from higher-level user code.
The server uses epoll to detect when the listening socket has an incoming connection to accept. This follows the usual socket(), bind(), listen(), and accept() functions. I've omitted the epoll code for brevity.
int server_socket = -1;
server_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
assert(server_socket != -1);
char* socket_path = "/tmp/test_sock";
struct sockaddr_un address;
memset(&address, 0, sizeof(address));
address.sun_family = AF_UNIX;
strncpy(address.sun_path, socket_path, strlen(socket_path));
int res = bind(server_socket, (struct sockaddr*)&address, sizeof(address));
assert(res == 0);
res = listen(server_socket, 20);
assert(res == 0);
int connection_socket = -1;
connection_socket = accept(server_socket, NULL, NULL);
assert(connection_socket != -1);
I then have a client which requests a connection using a socket() and connect() sequence.
int client_socket = -1;
client_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
assert(client_socket != -1);
char* socket_path = "/tmp/test_sock";
struct sockaddr_un address;
memset(&address, 0, sizeof(address));
address.sun_family = AF_UNIX;
strncpy(address.sun_path, socket_path, strlen(socket_path));
int res = connect(client_socket, (struct sockaddr*)&address, sizeof(address));
To allow some flexibility in the startup order of both applications without blocking the client on connect, I'm kicking off a 2nd thread to loop over the functions above until the connect() call succeeds. At that point the client code then sets up another epoll in order to monitor the client-side socket for events.
This leads me to my questions:
connect() can succeed only after the server has called listen() on the bound socket. Before that it will either give an ENOENT or ECONNREFUSED. Is there a way to get connect() to only succeed after the server has called accept()? I've also monitored the client sockets via epoll and it can become writable even before accept() is called.
Can the client detect disconnects if the server is stopped after listen() is called but before accept() is called? close() on the listening socket doesn't produce an epoll event. Am I left to rely on the user code at the level above to attempt a hand shake and give up after a time has passed and the server has not responded?
Are there any differences in the above behaviours between abstract and pathname-bound sockets?

Will Epoll work with UDP listening socket for having a event driven UDP server

I am trying to create a event driven multiple threads UDP/DTLS server. The design is based on the following concepts
Have a UDP socket where the Clients connects on
Use Epoll to ask for events on the UDP listen socket.
The UDP socket acts as a TCP listen socket and creates child fds that connect to the specific client. For this I have implemented a UDPAccept method for my object which has the pseudo code as shown below
UDPAccept(int fd,struct sockaddr * addr,
socklen_t * addr_len,void *sockBuf,size_t *read)
{
//sanity checks
int childfd = -1;
int error = 1;
socklen_t localLen,peerLen;
int family;
struct sockaddr_in local4,peer4;
struct sockaddr temp;
size_t maxLen = 65535;
getsockname(fd,(struct sockaddr *)&temp,&localLen);
family = temp.sa_family;
do
{
childfd = socket(family,SOCK_DGRAM,0);
//error handling
//handle IPV6
local4 = (sockaddr_in *)temp;
error = recvfrom( fd, sockBuf,
maxLen,0,(struct sockaddr *)&peer4,
&peerLen);
error = bind(childfd,(struct sockaddr *)&local4,sizeof local4);
error = connect(childfd,(struct sockaddr *)&peerV4,peerLen);
//handle error
}while(0);
if(addr != NULL && addr_len != NULL)
{
*addr_len = peerLen;
addr = &peerV4;
*read = error;
}
// error handling and cleanup
return childfd;
}
Add the child socket to Epoll table.
epoll_ctl(efd,EPOLL_CTL_ADD,newFd,&event);
Poll for events on the child and listen socket
currentSize = epoll_wait(efd,events,MAX_SOCKET_FD,timeout);
//handle errors
for(i = 0; i < currentSize;i++)
{
if(events[i].data.fd == listenUDP)
//call UDPAccept
// update local tables
else
//handle child fd events
}
Have multiple threads to the same thing, synchronize using locks during accept
Now my question is will epoll stop giving me POLLIN events on the listening socket because I have created a new UDP child connected socket to the client or will I have to handle it myself
It will deliver events on both sockets unless you remove the first socket from events.
But I'm wondering why you're doing this. You can use a single UDP socket for everything. It's much simpler.
Per the Linux man page on connect(), a filter will ensure only datagrams from the "connected" peer will be delivered to the new socket.
One caveat though... The bind() call will briefly take over the port from the listener until the connect call(). It's a small window, but can result in datagrams from other clients appearing on the "connected" socket. You can ignore them by validating the peer address.

SO_RCVTIMEO option on LwIP

I'm using LwIP with FreeRTOS. My project is based on the example on this URL FreeRTOS with LwIP project. I'm also using LPC1769 with LPCXpresso version 6. CMSIS version 2.
I'm using LwIP to stream MP3 files with a UDP socket. The transfer has a nice speed but the thing is that sometimes lwip_recvfrom blocks after thousands of operations.
I can never see the timeout condition. I think I'm doing something wrong.
The followed steps are:
int socket = lwip_socket(AF_INET, SOCK_DGRAM, 0);
if(lwip_setsockopt( socket,
SOL_SOCKET,
SO_RCVTIMEO,
(int)timeoutTimeInMiliSeconds,
sizeof(int)) == -1)
{
return -1;
}
....
if(lwip_bind(protocolConfig.socket,
(struct sockaddr *)&sLocalAddr,
sizeof(sLocalAddr)) == -1)
{
return -1;
}
bytesWritten = lwip_sendto( socket,
transmitBuffer,
transmitBufferIndex,
0,
(struct sockaddr *)&sDestAddr,
sizeof(sDestAddr));
.....
bytesReceived = lwip_recvfrom( socket,
receptionBuffer,
receptionBufferSize,
0,
NULL,
NULL);
if(bytesReceived < 0)
{
//Error stuff, this condition is never reached.
}
Somebody knows what's wrong here?
Problem solved.
lwip_setsockopt has this prototype:
int lwip_setsockopt(int socket, int level, int option_name,const void *option_value, socklen_t option_len);
And I was sending by copy the value of option_value.
The timeout is working fine.

How to re bind a udp socket in Linux

I am an experienced Linux socket programmer and am writing a server application which has many outgoing interfaces. Now server socket binds to a random source port in the start of the process along with INADDR_ANY.
Later at some point when submitting response to a specific node, i need to assign a fixed source ip address. The standard way to do this is calling bind. However, bind is called once for the port number, successive calls fail with invalid argument error.
Creating a new socket is not really a good choice since i will have to be doing this very often upon responding to some clients.
I have also explored SO and a lot of socket options such as IP_FREEBIND, but it doesn't quite suite my scenario.
Perhaps using IP_PKT_INFO and setting source address might work unless it suffers the same problem i.e. not allowing a socket once bound to INADDRANY to rebind to a fixed source ip latter.
Is there a way to unbind an existing socket or an alternate way to setting source ip address in outgoing packet?
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
printf("Failed creating socket\n");
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(1500);
addr.sin_addr.s_addr = INADDR_ANY;
// first bind succeeds
if ( (status = bind(sock, (struct sockaddr *) &addr, sizeof(addr))) < 0)
printf("bind error with port %s\n", strerror(errno));
struct sockaddr_in src_addr;
memset(&src_addr, 0, sizeof(struct sockaddr_in));
src_addr.sin_family = AF_INET;
if (inet_aton("10.0.2.17", &(src_addr.sin_addr)) == 0)
printf("Failed copying address\n");
// second bind fails
if((status = bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr))) < 0)
printf("re bind error with ip %s\n", strerror(errno));
Any ideas in this regard will be highly appreciated. I have gone through considerable material on sockets, SO etc. but no success yet.
I finally found the solution myself so accepting my own answer (shameless but correct plugin), supplemented with code sample.
I originally wanted to rewrite source address of an outgoing packet without creating the socket again where the socket was already bound. Calling bind multiple times fail for this case, and (in my particular situation), i was not able to just have separate sockets for each source ip and use it.
I found some references in IP_PACKET_INFO but it was a pain to get it to work correctly. Following reference was helpful.
Setting source of udp socket
Sample Code
Here is a trivial application which creates a udp socket, binds it to a local port, then before sending a particular message, it appends the outgoing source ip address. Keeping in mind that in my case, i created a sudo interface and assigned it another ip. The send call will fail if this is not the case.
int status=-1;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
printf("Failed creating socket\n");
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
struct sockaddr_in bind_addr;
memset(&bind_addr, 0, sizeof(struct sockaddr_in));
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons(44000); // locally bound port
if((status = bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) < 0)
printf("bind error with port %s\n", strerror(errno));
// currently using addr as destination
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(80); // destination port
if (inet_aton("74.125.236.35", &(addr.sin_addr)) == 0)
printf("Failed copying remote address\n");
else
printf("Success copying remote address\n");
struct sockaddr_in src_addr;
memset(&src_addr, 0, sizeof(struct sockaddr_in));
src_addr.sin_family = AF_INET;
if (inet_aton("10.0.2.17", &(src_addr.sin_addr)) == 0)
printf("Failed copying src address\n");
else
printf("Success copying src address\n");
char cmbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
char msg[10] = "hello";
int len = strlen(msg);
struct msghdr mh;
memset(&mh, 0, sizeof(mh));
struct cmsghdr *cmsg;
struct in_pktinfo *pktinfo;
struct iovec iov[1];
iov[0].iov_base = msg;
iov[0].iov_len = len;
mh.msg_name = &addr; // destination address of packet
mh.msg_namelen = sizeof(addr);
mh.msg_control = cmbuf;
mh.msg_controllen = sizeof(cmbuf);
mh.msg_flags = 0;
mh.msg_iov = iov;
mh.msg_iovlen = 1;
// after initializing msghdr & control data to
// CMSG_SPACE(sizeof(struct in_pktinfo))
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
//src_interface_index 0 allows choosing interface of the source ip specified
pktinfo->ipi_ifindex = 0;
pktinfo->ipi_spec_dst = src_addr.sin_addr;
int rc = sendmsg(sock, &mh, 0);
printf("Result %d\n", rc);
The key statement is
pktinfo->ipi_spec_dst = src_addr.sin_addr;
where we are specifying the source ip address to be used. The rest of things like cmsg struct etc. are merely used in order to be able to write ipoktinfo struct ourselves
There is no way to unbind and rebind an existing socket.
Why don't you create a socket for each interface instead? Since the UDP/IP protocol is connectionless, you can choose the source IP address by choosing which socket you use to send the reply with; there is no need to use the same socket the incoming datagram was received on.
The downsides are that you can no longer bind to the wildcard address, and you must use select(), poll(), multiple threads, or some other mechanism to receive datagrams from multiple sources concurrently. You'll also need some logic to efficiently pick the socket based on the client IP address.
In most cases, I suspect that adding a few route entries to route each remote IP address to the desired host IP address, and using a separate socket for each host IP address and port combination, solves the issues perfectly -- and using the very efficient kernel functionality to do so. While the behaviour may be an application requirement, I suspect it is better solved using the network interface configuration instead. Unfortunately, often the requirements are written by semi-functional idiots better suited for manual labor, and your hands are tied.. if so, I commiserate.
If you have a test network with workstations having multiple physical network interfaces, I can provide a simple example C99 test program you can use to verify the design works.

Have responses to UDP datagrams picked up by another process?

I'm trying to implement a basic UDP protocol wherein a Sender sends a UDP datagram to a Service, which then sends a response datagram back, using the source address and source port from the incoming datagram.
Normally you'd have the Sender also listen for the response on that port. But I want the response to be picked up by a separate program (the Listener) also running on that host. So:
On host A, Listener starts and binds to port 12345, and blocks on recvfrom.
On host A, Sender sends datagram to Service running on host B, setting the source address and port to host A, port 12345.
Service on host B sends a response to host A port 12345.
Response is picked up by Listener.
Setting the source address and port is done by binding to them. So I need both Sender and Listener to bind to the same port. Setting SO_REUSEADDR in both allows this. Note that I'm not using multicast here.
But the responses aren't reliably being picked up by Listener. There are two exceptions I've observed:
I find that if the Sender closes the socket immediately after sending the first datagram, then the response will get to the Listener.
Alternatively, if the Sender is started first and binds before the Listener, the responses will get picked up by the Listener.
I've been working from examples from the internet and haven't found documentation that clearly describes what should happen. But a few places I've seen have hinted that, for Unicast, only the most recent process to bind to the port will receive datagrams sent to it.
My question is, can I send UDP datagrams so that responses (sent using the source address and port) will be picked up by another process? If the above process can't be made to work, is there a way to set the source information on an outgoing datagram without binding to that port?
A few other points:
Each process should be started independently and be able to be restarted without interfering with the other. So I don't think I can have one open the socket and spawn the other.
I don't need to receive packets from both processes. One process only sends, and the other only receives.
Ideally, the solution would be portable enough to run on common Unixes and Windows.
Finally, if it's simply not possible then I'll fall back to using a single process to perform both functions. I'm not too stressed about it but I am interested in doing it if it is possible somehow. :-)
Networking code follows...
Sender code
void run(Options *options)
{
struct sockaddr_in si_me, si_other;
int s;
socklen_t slen = sizeof(si_other);
int reuse = 1;
struct hostent *he;
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
die("socket");
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != 0)
die("setsockopt");
// Bind to the "listen port", so that outgoing datagrams have the correct source information
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(options->listen_port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me)) != 0)
die("bind");
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(options->service_port);
if (!(he = gethostbyname2(options->service_host, AF_INET)))
die("gethostbyname2");
memmove(&si_other.sin_addr.s_addr, he->h_addr, he->h_length);
while (1)
{
int len;
char *buf;
// Create outgoing message in buf
...
if (sendto(s, buf, len, 0, (struct sockaddr *) &si_other, slen) == -1)
die("sendto");
}
close(s);
}
Listener code
static void run(Options *options)
{
struct sockaddr_in si_me, si_other;
int s;
socklen_t slen = sizeof(si_other);
char buf[BUFLEN];
int reuse = 1;
if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
die("socket");
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != 0)
die("setsockopt");
// Bind to the same "listen port" to pick up responses to datagrams sent by Sender
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(options->listen_port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, (struct sockaddr *) &si_me, sizeof(si_me)) == -1)
die("bind");
while (1)
{
int nr;
nr = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen);
if (nr == -1)
die("recvfrom");
// Process the received message
...
}
close(s);
}
A related question is Using netcat to send a UDP packet without binding, where one answer seems to suggest it should be possible using SO_SOCKADDR, but did not quite explain how it would work in my case.
is there a way to set the source information on an outgoing datagram
without binding to that port?
There is no portable way. A solution for Linux, using IP_PKTINFO, is this answer to How to re bind a udp socket in Linux.
1: You can send from different port on B
A binds 12345 sends to B:12345
B:12345 - process 1 - recv
B:12346 - process 2 - send to A:12345
2: You can construct packet with fake back address with raw sockets
First solution is better

Resources