Skip to content
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

Bidirectional udp #12

Merged

Conversation

g-arjones
Copy link
Contributor

This will add support for a new URI format udp://ip_address:remote_port[:local_port] that will allow udp communication with a single peer.

@@ -253,6 +254,8 @@ class Driver
* The read_port port can be 0 if the local port does not need to be fixed.
*/
void openUDP(std::string const& hostname, int remote_port);
void openUDPBidirectional(std::string const& hostname, int out_port, int in_port);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation is missing

@g-arjones
Copy link
Contributor Author

@jmachowinski Forgot to push that, sorry.

@@ -194,6 +194,18 @@ void Driver::openURI(std::string const& uri)
{ // UDP udp://hostname:remoteport
if (marker == string::npos)
throw std::runtime_error("missing port specification in udp:// URI");

string::size_type second_marker = device.find_last_of(":");
int extended_info = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declare local variables in the deepest scope possible, and where they are used first.

@g-arjones
Copy link
Contributor Author

g-arjones commented Sep 6, 2016

I remember having dropped packet issues in the past if you get packets in a POSIX socket before you call read() and couldn't find any reference to what the expected behavior is so I just think it is safer to read() and then wirte() rather than the other way around. And readPacket() is sync, hence the threads. Do you think it is better to remove the threads?

@doudou
Copy link
Member

doudou commented Sep 6, 2016

I remember having dropped packet issues in the past if you get packets in a POSIX socket before you call read()

I very highly doubt that. Very. Think about it: there is always a time where the receiver is not reading: between the two calls to read. What if a packet arrives there ?!? You can have buffer overruns, especially in UDP, but other than that ...

So, yes, I would very much prefer removing the threads. I like to have non-suspicious tests ...

string::size_type second_marker = device.find_last_of(":");
if (second_marker != string::npos)
{
int remote_port = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int remote_port = <actual value> there initializing it to assign it one line later is just noise.

@jmachowinski
Copy link
Contributor

The buffer overrun happens quite fast.
setsockopt(sd_receiver, SOL_SOCKET, SO_RCVBUF, &newSize, sizeof(int))
helps in this case.

@doudou
Copy link
Member

doudou commented Sep 8, 2016

The buffer overrun happens quite fast.

While we should definitely control it, and thank you for pointing it out, "quite fast" is probably a very subjective measurement. The default receive buffer on my machine is 213kiB, which given that Linux limits UDP datagrams to the PMTU by default is 70 datagrams or something. I don't see that as horribly fast unless the pulling process (in most cases, the driver oroGen component) would really be sleepy.

In any case, we should probably have a way to control these. Proposal

@jmachowinski
Copy link
Contributor

In our use case we were streaming multiple ports from one system to one UDP port (including images) so it overrun quite fast....
Any way, I agree adding this to the iodriver seems to be a good idea.

@@ -247,6 +257,73 @@ void Driver::openIPServer(int port, addrinfo const& hints)
setMainStream(new UDPServerStream(sfd,true));
}

void find_addr(const char *hostname, const char *port, addrinfo const& hints, struct sockaddr *addr, size_t *addr_len)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be static.

@g-arjones
Copy link
Contributor Author

g-arjones commented Sep 8, 2016

Isin't that a bit counterintuitive? The streams/fds are created and set in the openIP* methods (openIPServer, openIPClient...). To make openIPBidirectional a static helper function I would have to pass a reference to the socket descriptor between the helper itself and the method that will create the stream. Is it what you prefer?

@doudou
Copy link
Member

doudou commented Sep 8, 2016

The only one that makes sense is openIPClient. openIPServer and openIPBidirectional are currently UDP-specific because they need to set a different main stream class.

Unless I am mistaken, the creation and binding of the server-side socket is copy/pasted between openIPServer and openIPBidirectional. I think it would make a lot of sense that the creation of the IP server socket be refactored as a helper methods. E.g. int createIPServerSocket(int port, addrinfo const& hints), which created, binds and returns the file descriptor. It is actually the exact same piece of code in openIPServer and openIPBidirectional. Then, refactor:

  • openUDP create the server socket, create the stream in the server case
  • openUDPBidirectional create the server socket, resolve the peer, create the stream

Get rid of the openIPServer and openIPBidirectional methods completely.

@g-arjones
Copy link
Contributor Author

Makes sense. I was avoiding touching existing methods because there are no test cases for those but there is indeed a lot of repeated code and some refactoring would be good... 👍

@g-arjones
Copy link
Contributor Author

I think it looks much better now!

This is important to prevent leaking server socket descriptor in case createIPClientSocket throws
@g-arjones
Copy link
Contributor Author

Ping?

@doudou
Copy link
Member

doudou commented Sep 13, 2016

Looks good. Thanks !

@doudou doudou merged commit afe5517 into rock-core:master Sep 13, 2016
@doudou doudou deleted the bidirectional_udp branch September 13, 2016 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants