I have been putting off writing about the TCP part for quite some time but I guess there is nothing else I can talk about apart from that. TCP requires a handshake before data can be sent/received. This is done by first sending a SYN which is replied by a SYN + ACK this is then ACKed back. Finally a PSH + ACK is sent to send data. After this you should receive data and close the connection but since this is only a very basic html data sender it will be a bit naughty and just go quite after sending.

The TCP header has the following layout:

typedef struct
{
  IPhdr ip;
  unsigned int sourcePort;
  unsigned int destPort;
  unsigned char seqNo[4];
  unsigned char ackNo[4];
  unsigned char NS:1;
  unsigned char reserverd : 3;
  unsigned char hdrLen : 4;
  unsigned char FIN:1;
  unsigned char SYN:1;
  unsigned char RST:1;
  unsigned char PSH:1;
  unsigned char ACK:1;
  unsigned char URG:1;
  unsigned char ECE:1;
  unsigned char CWR:1;
  unsigned int wndSize;
  unsigned int chksum;
  unsigned int urgentPointer;
  //unsigned char options[8];
}TCPhdr;

We are sending HTML data so the destination port will be 80 the source port can be anything but in general it is a value greater than 50,000 and it will change for every different connection. As this will be only html to one server we will keep this constant. SeqNo is the sequence number and is increased by how much data the server you are communicating with received. Its initial number is random and for this application it was set to 1 just to make it easier to see in wireshark. The AckNo is the acknowledgement number and is like SeqNo except is about the data that the server is sending. Its initial number is 0 but when the first packet is replied it will be set to a random number by the server.

The next part is a bunch of different flags. NS and reserved are not used and are set to zero. Hdrlen is the length of the header in 4 bytes. The rest of the flags are set depending on what data is being sent/received.

WndSize is the maximum size of data that can be sent we don’t have very much room and is set to the size of the buffer – the size of this header. The chksum is calculated in the same way as UDP chksum so see the previous post. Urgent point is used in fragmented packets and will not be used. I have an array of chars called options commented out which can also be used for specifying other things but they are optional.

The first packet to send was therefore a simple SYN packet with everything set to default values. When the server responded we received a packet that was a SYN + ACK. To reply to this first all of the ports, IP address’, MAC address’ and AckNo/SeqNo had to be swapped. After this the SeqNo number has to be incremented if there is a SYN and incremented by the amount of data if there is data. Next the SYN flag is removed so that it was just a ACK packet and finally all lengths and checksums are recalculated. This packet is then sent and just after it another packet is sent that has our data inside of it as well. For a test message the following was sent to google.com.

"GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n"

I haven’t actually got around to processing the reply messages but just from debugging I was able to see a reply with the correct data inside. The next step is therefore to tidy up the code and try make a cleaner finish to sending data.

Advertisements