#include "platform.h" #include "tcp.h" #include "enc28j60.h" #include "eth.h" #include "ip.h" #include "http.h" /* ========================================================================== TCP receive and decode */ void tcp (unsigned char *buff) { unsigned char tcp_len = 0; unsigned char ip_len = 0; unsigned int http_len = 0; struct TCP_header *tcp; tcp = (struct TCP_header *)&buff[34]; switch (buffer[TCP_FLAGS]) { // tcp flags... case TF_SYN: // SYN tcp_send(0, buffer, 0x12,0,0); break; case (TF_ACK | TF_PSH): // PSH+ACK tcp_len = ((buffer[TCP_HEDLEN]) >> 4) * 4; ip_len = (buffer[IP_HEDLEN] & 0x0F) * 4; http_len = (((unsigned int)buffer[IP_TOTLEN_H] << 8) + buffer[IP_TOTLEN_L]) - tcp_len - ip_len; http ((tcp_len + ip_len + 14), http_len, buffer); break; case TF_ACK: // ACK ack_received(0x10); break; case TF_RST: // RST tcp_res(); break; case (TF_FIN | TF_ACK): // FIN+ACK ack_received(0x11); break; case (TF_FIN | TF_PSH | TF_ACK): // FIN + PSH + ACK tcp_res(); break; } } /* ========================================================================== Generate TCP and lower headers */ void tcp_send (unsigned int len, unsigned char *buff, unsigned char flags, unsigned int lenack, int lensour) { unsigned int tempport; unsigned long tempack, templngb; struct TCP_header *tcp; tcp = (struct TCP_header *)&buff[34]; eth(buff); // eth header generate buff[16] = ((IP_TCP_HEADERLENGHT + len) & 0xFF00) >> 8; // total length buff[17] = ((IP_TCP_HEADERLENGHT + len) & 0x00FF); ip(buff); // ip header generate tempport = tcp->TCP_sourcePort; // swap source and destination tcp port tcp->TCP_sourcePort = tcp->TCP_destPort; tcp->TCP_destPort = tempport; tempack = tcp->TCP_SeqNumb_0; // tcp windows number calculate tempack += (unsigned long)((unsigned long)tcp->TCP_SeqNumb_1 << 8); tempack += (unsigned long)((unsigned long)tcp->TCP_SeqNumb_2 << 16); tempack += (unsigned long)((unsigned long)tcp->TCP_SeqNumb_3 << 24); templngb = tcp->TCP_AckNumb_0; templngb += (unsigned long)((unsigned long)tcp->TCP_AckNumb_1 << 8); templngb += (unsigned long)((unsigned long)tcp->TCP_AckNumb_2 << 16); templngb += (unsigned long)((unsigned long)tcp->TCP_AckNumb_3 << 24); if (lenack) { if (lenack != 0xFFFF) { if (lenack == 0xFFFE) { tempack--; } else { tempack = lenack + tempack; tcp->TCP_Window = 0xF6FD; } } } else { tempack++; tcp->TCP_Window = 0xD016; } tcp->TCP_AckNumb_0 = (unsigned char) tempack; // tcp ack number tcp->TCP_AckNumb_1 = (unsigned char) (tempack >> 8); tcp->TCP_AckNumb_2 = (unsigned char) (tempack >> 16); tcp->TCP_AckNumb_3 = (unsigned char) (tempack >> 24); if (lensour) templngb += lensour; tcp->TCP_SeqNumb_0 = (unsigned char) templngb; // tcp seq number tcp->TCP_SeqNumb_1 = (unsigned char) (templngb >> 8); tcp->TCP_SeqNumb_2 = (unsigned char) (templngb >> 16); tcp->TCP_SeqNumb_3 = (unsigned char) (templngb >> 24); tcp->TCP_DataOffset = 0x50; // data offset tcp->TCP_Flags = flags; // tcp flags tcp->TCP_Checksum = 0; // tcp checksum is calculate in later tcp->TCP_UrgPointer = 0; // urgent pointer - standard tcp_send_packet (len, buff); } /* ========================================================================== Send TCP packet - generate checksum - write to chip - send */ void tcp_send_packet (unsigned int len, unsigned char *buff) { unsigned int sum; unsigned char tempch; struct TCP_header *tcp; unsigned int txbuf; tcp = (struct TCP_header *)&buff[34]; sum = tcp_checksum(len, buff); // checksum tempch = (unsigned char) sum; sum = sum >> 8; sum += ((unsigned int)tempch << 8); tcp->TCP_Checksum = sum; if (!nic_tx_alloc(&txbuf)) return; // write buffer to chip netbuf_wr_seek(txbuf, NB_SEEK_SET); netbuf_write(buff, IP_TCP_HEADERLENGHT + ETH_HEADERLENGHT +len); netbuf_close(); nic_tx(IP_TCP_HEADERLENGHT + ETH_HEADERLENGHT +len); // send } /* ========================================================================== TCP checksum calculate */ unsigned int tcp_checksum (unsigned int len, unsigned char *buff) { unsigned int tmpcnt; unsigned long sum = 0; for (tmpcnt = 26; tmpcnt < (IP_TCP_HEADERLENGHT + ETH_HEADERLENGHT + len); tmpcnt++) { sum += ((unsigned int)buff[tmpcnt] << 8); tmpcnt++; sum += buff[tmpcnt]; } sum += 6 + TCP_HEADERLENGHT + len; while (sum>>16) { sum = (sum & 0xFFFF)+(sum >> 16); } sum = ~sum; return ((unsigned int) sum); } /* ========================================================================== TCP res */ void tcp_res (void) { unsigned char macsum, cliok; macsum = buffer[6] + buffer[7] + buffer[8] + buffer[9] + buffer[10] + buffer[11] + buffer[34] + buffer[35]; cliok = 0; while (cliok <= MAX_CLIENT && client[cliok][0] != macsum) cliok++; if (client[cliok][0] == macsum) client[cliok][0] = 0; } /* ========================================================================== ACR receive - decode and responze */ void ack_received(unsigned char tcpflags) { unsigned char macsum, cliok; // unsigned int count = 0x36; tohle nebylo nikde pouzito // unsigned int counta = 0x00; // unsigned int countblock = 0x00; // unsigned char number_up; macsum = buffer[6] + buffer[7] + buffer[8] + buffer[9] + buffer[10] + buffer[11] + buffer[34] + buffer[35]; cliok = 0; while (cliok <= MAX_CLIENT && client[cliok][0] != macsum) cliok++; if (client[cliok][0] == macsum) { switch (client[cliok][1]) { case 0xFC: case 0xFE: if (tcpflags == 0x10) { // ACK if (client[cliok][2] != 0xA0) { if (client[cliok][1] == 0xFC) { tcp_send(0, buffer, 0x11,0xFFFF,0); } else { tcp_send(0, buffer, 0x11,0xFFFF,0); } client[cliok][2] = 0xA0; } else { client[cliok][1] = 0xFD; } } if (tcpflags == 0x11) { // FIN ACK tcp_send(0, buffer, 0x11,0,0); client[cliok][1] = 0xFD; } break; case 0xFD: if (tcpflags == 0x11) { tcp_send(0, buffer, 0x10,0,0); } client[cliok][0] = 0; break; } } }