Opened 6 years ago

Closed 6 years ago

#9678 closed bug (fixed)

Cannot send and receive through the same socket

Reported by: markh Owned by: phoudoin
Priority: normal Milestone: R1
Component: Network & Internet/IPv4 Version: R1/alpha4.1
Keywords: Cc: phoudoin
Blocked By: Blocking:
Has a Patch: no Platform: All

Description

When trying to receive data from a socket I have previously sent data through, I get a connection refused error. A workaround is to use a second socket to send the data. I attached two files:

  • socket_test_send_recv_1_socket.c: Uses only one socket and fails.
  • socket_test_send_recv_2_sockets.c: Uses two sockets and works.

The first construction is used by Postgresql to check if it can start the statistics collector and this now fails on Haiku.

Attachments (2)

socket_test_send_recv_1_socket.c (4.9 KB ) - added by markh 6 years ago.
socket_test_send_recv_2_sockets.c (5.0 KB ) - added by markh 6 years ago.

Download all attachments as: .zip

Change History (10)

by markh, 6 years ago

comment:1 by phoudoin, 6 years ago

Thanks Mark for the ticket.

Meanwhile, could you try in the one socket scenario to skip the connect() step and use sendto(pgStatSock, &test_byte, 1, 0, & pgStatAddr, alen) instead of calling plain send()?

Oh, BTW, closesocket() was needed under BeOS only. You can use close() now, and it's better to remove this old BeOS-specific from PostgresSQL port.

comment:2 by phoudoin, 6 years ago

Cc: phoudoin added

comment:3 by phoudoin, 6 years ago

Just test it: when skipping connect() and using sendto() instead, send and receive through the same socket does works as expected.

Which means that connect() is the culprid here. Well, not the syscall, but the UdpEndpointManager::ConnectEndpoint() one, I fear.

comment:4 by phoudoin, 6 years ago

looking at udp_endpoints KDL command, it seems that the local (ephemeral) port bound at bind() step is replaced by the implicit bind done at UdpEndpointManager::ConnectEndpoint()'s end, with a new ephemeral local port. The peer address/port pair being the first bound one, the data sent is refused as no local address match anymore.

Will see next how to fix that - without breaking everything else ;-)

comment:5 by phoudoin, 6 years ago

Owner: changed from zooey to phoudoin
Status: newin-progress

comment:6 by phoudoin, 6 years ago

If I'm not mistaken, problem is here: http://cgit.haiku-os.org/haiku/tree/src/add-ons/kernel/network/protocols/udp/udp.cpp#n371

When the local address is not empty, bound port is not kept, overwritten by routeToDestination's interface address port, which is 0 for obvious reason, leading to a new ephemeral port being bound to endpoint.

comment:7 by axeld, 6 years ago

Thanks for working on this, phoudoin! You may want to add the test to our set of networking test applications -- that we should one day transform into proper unit tests.

comment:8 by phoudoin, 6 years ago

Resolution: fixed
Status: in-progressclosed

Fixed in hrev45520.

Note: See TracTickets for help on using tickets.