Erlang sockets: sending back FIN/RST early? - tcp

tl;dr : Wireshark says that gen_tcp is sending FIN,RST flags before I can finish receiving all of my data...
I'm receiving data from an active socket via gen_tcp. It's coming from an (un-encrypted) OpenSSL socket via BIO_write() (see http://linux.die.net/man/3/bio_write) and gen_tcp is listening with the following options:
[binary,{packet,0},{active,true},{reuseaddr,false},{recbuf,256000}]
I'm running this using the Win32 distro of Erlang/OTP and expect to receive some pretty large data, thus the large recbuf. This has worked okay for me in the past.
I'm getting only the first 1516 bytes from each total packet that's sent out, then gen_tcp sends back a FIN, and I can't figure out why that is.
Here's a snap of my Wireshark dump:
*37.184 is the Erlang receiver, *35.125 is the OpenSSL sender.
The blue line is the "header" packet, sending over the protocol version. The chunk that follows with the data length of "Len=1460" is the first big data blob. Then the ACK # #3, and Erlang barfs with a FIN # #4
The yellow line is the last chunk of data successfully sent over.
Any ideas?

Related

Identifying last packet in a message sent by TCP

Say we have sender A sending a message to receiver B using TCP. Say the message to be sent from A to B is split into three packets of length 500 bytes, 500 bytes and 50 bytes, to be sent in that order. How does A indicate to B that the packet of length 50 bytes is the last part of the message? I can understand that an ACK from B to A, sent every other packet received by B, indicates using the sequence number how much data has been received by B since the last ACK was sent by B. I read that FIN is used to terminate the connection between the sender and receiver. However, I can't find a description of how the the last packet, of a message split into several packets, is indicated. I'm thinking the packets have to be reassembled, in order, before the message is sent to the receiving application. I think that as one of TCPs actions is to split the message into packets, there must be some way of the sender flagging the last packet of a message has been sent.
I think that as one of TCPs actions is to split the message into
packets
No, TCP takes a stream of data and segments it into PDUs called segments. It is IP that uses the TCP segments as the payload of IP packets, which are in turn the payload of the data-link protocol, e.g. ethernet, frames.
However, I can't find a description of how the the last packet, of a
message split into several packets, is indicated.
Something like that is up to a higher protocol, e.g. HTTP. I think you are looking at TCP the wrong way. A TCP connection is like a bidirectional pipe; whatever you put in one end comes out the other end. TCP has no idea of the data structure, it just sends whatever it gets from the application or application-layer protocol. When an application or application-layer protocol is through using the connection, it tells TCP to tear it down.
The receiving TCP simply receives data and reorders it, asking for lost or missing segments. It passes properly ordered data up to the application or application-layer protocol, having no idea of the data structure because it is just a data stream to TCP.
Also, remember that both ends of a TCP connection are peers that can send and receive, and either end can send a segment with FIN that tells the other end that it is done sending, but the end sending the FIN is obligated to continue to receive until the other end also sends a FIN to say it is done sending. Either side could also kill the connection with a RST segment.
there must be some way of the sender flagging the last packet of a
message has been sent.
Probably, but that is not the job of TCP, that is up to the application or application-layer protocol. When the application-layer is done, it tells TCP to close, and that starts the FIN process. TCP has no idea what is the last part of a message is because it knows nothing about the data. It keeps the pipe open until it is told to close it.

TCP Server sends [ACK] followed by [PSH,ACK]

I am working on a high-performance TCP server, and I see the server not processing fast enough on and off when I pump high traffic using a TCP client. Upon close inspection, I see spikes in "delta time" on the TCP server. And, I see the server sending an ACK and 0.8 seconds later sending PSH,ACK for the same seqno. I am seeing this pattern multiple times in the pcap. Can experts comment on why the server is sending an ACK followed by a PSH,ACK with a delay in between?
TCP SERVER PCAP
To simplify what ACK and PSH means
ACK will always be present, it simply informs the client what was the last received byte by the server.
PSH tells the client/server to push the bytes to the application layer (the bytes forms a full message).
The usual scenario you are used to, is more or less the following:
The OS has a buffer where it stores received data from the client.
As soon as a packet is received, it is added to the buffer.
The application calls the socket receive method and takes the data out of the buffer
The application writes back data into the socket (response)
the OS sends a packet with flags PSH,ACK
Now imagine those scenarios:
step 4 does not happen (application does not write back any data, or takes too long to write it)
=> OS acknowledge the reception with just an ACK (the packet will not have any data in it), if the application decides later on to send something, it will be sent with PSH,ACK.
the message/data sent by the server is too big to fit in one packet:
the first packets will not have PSH flag, and will only have the ACK flag
the the last packet will have the flags PSH,ACK, to inform the end of the message.

How does TCP PSH work?

PSH is a way to send data via TCP. Besides that, I can find very little info on how to implement it properly.
Here is what interests me:
Let's say, server window is 8000 bytes, and I send 2 requests with 150 and 600 bytes. Do I get some sort of confirmation that the data has been received? Can I somehow trigger a confirmacion?
I've seen some ACK packets, which does not contain PSH but do contain some sort of payload data (Wireshark marks it as "TCP segment data"). Is this data passed on to user, and if it is, why do we need PSH flag?
TCP PSH generally doesn't 'work' at all. Berkely-derived TCP implementations completely ignore it.
Source: W.R. Stevens, TCP/IP Illustrated, vol I: 20.5 PUSH Flag.
#Arsen: Answering to the second part of your question "why do we need PSH flag?"
The PSH flag in the TCP header informs the receiving host that the data should be pushed up to the receiving application immediately.
We are using PSH flag to exchange Time Stamp value between two servers.
i am assuming , if we set push flag , packet wont wait in receive buffer , it will directly send to receiver.
The data doesn't sit waiting in the receive buffer anyhow.
TCP apps must go out of their way to have the TCP layer bulk up a few packets and deliver full data buffers.
In fact its somewhat frustrating to see applications allocate 64KB buffers to receive data and see them getting a gazillion 1480/1472 byte messages.

How to know when you finish receiving a TCP stream?

I'm not sure how to tell in TCP when the sender finished sending me the information.
For example if A needs to send 200 bytes to B, how will B know that A finished sending, and that the information is ready to be transferred to the application layer?
There's the FIN flag, but as far as I know it's only there to symbolizes that your going to close the connection.
Thanks.
TCP has no obligation to tell the receiver when the sender has finished sending data on the connection. It can't because it has no understanding of the higher level protocol data it's transporting.
However it will tell you if the connection closes (then you'll see a FIN, FIN-ACK) sequence in a network trace. From a programming perspective, assuming that you're using C the function recv will return 0 when the peer closes the connection.
You define a protocol such as first sending a 4 byte int in a specified byte order which indicates how many bytes will follow in the message body.
If you're on unix/linux, select and poll can signal you that the other end finished transfer (did a half/full close). read will also return with an error if you've read all the data and want to read from a closed connection.
If you do multiple transfers on one connection and want to signal the end of a "package" you have to build that into your protocol.

Building a webserver, client doesn't acknowledge HTTP 200 OK frame

I'm building my own webserver based on a tutorial.
I have found a simple way to initiate a TCP connection and send one segment of http data (the webserver will run on a microcontroller, so it will be very small)
Anyway, the following is the sequence I need to go through:
receive SYN
send SYN,ACK
receive ACK (the connection is now established)
receive ACK with HTTP GET command
send ACK
send FIN,ACK with HTTP data (e.g 200 OK)
receive FIN,ACK <- I don't recieve this packet!
send ACK
Everything works fine until I send my acknowledgement and HTTP 200 OK message.
The client won't send an acknowledgement to those two packages and thus
no webpage is being displayed.
I've added a pcap file of the sequence how I recorded it with wireshark.
Pcap file: http://cl.ly/5f5/httpdump2.pcap
All sequence and acknowledgement numbers are correct, checksum are ok. Flags are also right.
I have no idea what is going wrong.
I think that step 6. should be just FIN, without ACK. What packet from the client are you ACKing at that place? Also I don't see why 4. should be an ACK instead of just a normal data packet - the client ACKed the connection at 3.
This diagram on TCP states might help.
WireShark says (of the FIN packet):
Broken TCP: The acknowledge field is
nonzero while the ACK flag is not set
I don't know for sure that's what's causing your problem, but if WireShark doesn't like that packet, maybe the client doesn't either. So, it should be FIN+ACK, or you should set the acknowledge field to 0.
If that doesn't solve it, you might also try sending the data first, then a separate FIN packet. It's valid to include data with the FIN, but it's more common to send the FIN by itself (as seen in the other pcap trace you posted earlier).
Also, you should probably be setting the PUSH flag in the packet with the 200 OK
Finally, I don't see any retransmission attempts for the FIN packet - is that because you stopped the capture right away?
The IP length field was consequently counting 8 bits too much. I made a mistake in my calculations. Everythings works like a charm now!

Resources