📄 tinytcp.c
字号:
/* do IP */ if ( ip->destination == lfix(sin_lclINAddr) && in_GetProtocol(ip) == 6 && checksum(ip, in_GetHdrlenBytes(ip)) == 0xFFFF ) { tcp_Handler(ip); } } x = clock_ValueRough() - start; timeout -= x; } return ( 1 );}#else/* busy-wait loop for tcp. Also calls an "application proc" */int tcp_receive(procref application){ longword timeout, start; int x; timeout = clock_ValueRough() + tcp_RETRANSMITTIME; while (tcp_allsocs) { start = clock_ValueRough(); if (ip_Handler() == 0) { if ( clock_ValueRough() > timeout ) { tcp_Retransmitter(); timeout = clock_ValueRough() + tcp_RETRANSMITTIME; } application(); continue; } x = clock_ValueRough() - start; timeout -= x; } return (1);}#endif /* DHCP_SUPPORT */#endif /* FTP_CLIENT_SUPPORT *//* * Write data to a connection. * Returns number of bytes written, == 0 when connection is not in * established state. */int tcp_Write(tcp_Socket *s, byte *dp, int len) { int x; if ( s->state != tcp_StateESTAB ) len = 0; if ( len > (x = tcp_MaxData - s->dataSize) ) len = x; if ( len > 0 ) { Move(dp, &s->data[s->dataSize], len); s->dataSize += len; //tcp_Flush(s); /*TODO*/ } return ( len ); }/* * Send pending data */void tcp_Flush(tcp_Socket *s) { if ( s->dataSize > 0 ) { s->flags |= tcp_FlagPUSH; tcp_Send(s); } }/* * Handler for incoming packets. */void tcp_Handler(in_Header *ip){ tcp_Header *tp; tcp_PseudoHeader ph; int len; int diff; tcp_Socket *s; word flags; len = in_GetHdrlenBytes(ip); tp = (tcp_Header *)((byte *)ip + len); len = wfix(ip->length) - len; /* demux to active sockets */ for ( s = tcp_allsocs; s; s = s->next ) if ( s->hisport != 0 && wfix(tp->dstPort) == s->myport && wfix(tp->srcPort) == s->hisport && lfix(ip->source) == s->hisaddr ) break; if ( s == NULL ) { /* demux to passive sockets */ for ( s = tcp_allsocs; s; s = s->next ) if ( s->hisport == 0 && wfix(tp->dstPort) == s->myport ) break; } if ( s == NULL ) { return; } /* save his ethernet address */ MoveW(&((((eth_Header *)ip) - 1)->source[0]), &s->hisethaddr[0], sizeof(eth_HwAddress)); ph.src = ip->source; ph.dst = ip->destination; ph.mbz = 0; ph.protocol = TCP_PROTO; ph.length = wfix(len); ph.checksum = wfix(checksum(tp, len)); if ( checksum(&ph, sizeof ph) != 0xffff ) { return; } flags = wfix(tp->flags); if ( flags & tcp_FlagRST ) { s->state = tcp_StateCLOSED; s->dataHandler(s, 0, -1,SABORT); tcp_Unthread(s); return; } switch ( s->state ) { case tcp_StateLISTEN: if ( flags & tcp_FlagSYN ) { s->acknum = lfix(tp->seqnum) + 1; s->hisport = wfix(tp->srcPort); s->hisaddr = lfix(ip->source); s->flags = tcp_FlagSYN | tcp_FlagACK; tcp_Send(s); s->state = tcp_StateSYNREC; s->unhappy = TRUE; s->timeout = tcp_TIMEOUT; } break; case tcp_StateSYNSENT: if ( flags & tcp_FlagACK ) { if (lfix(tp->acknum) != (s->seqnum + 1)) { s->flags = tcp_FlagRST; tcp_Send(s); s->flags = tcp_FlagSYN; } } if ( flags & tcp_FlagSYN ) { s->acknum++; s->flags = tcp_FlagACK; s->timeout = tcp_TIMEOUT; if ( (flags & tcp_FlagACK) && lfix(tp->acknum) == (s->seqnum + 1) ) { s->state = tcp_StateESTAB; s->seqnum++; s->acknum = lfix(tp->seqnum) + 1; s->unhappy = FALSE; tcp_Send(s); /*DRB Added*/ s->dataHandler(s, 0, 0,SOPEN); } else { s->state = tcp_StateSYNREC; } } break; case tcp_StateSYNREC: if ( flags & tcp_FlagSYN ) { s->flags = tcp_FlagSYN | tcp_FlagACK; tcp_Send(s); s->timeout = tcp_TIMEOUT; } if ( (flags & tcp_FlagACK) && lfix(tp->acknum) == (s->seqnum + 1) ) { s->flags = tcp_FlagACK; s->seqnum++; s->unhappy = FALSE; s->state = tcp_StateESTAB; s->timeout = tcp_TIMEOUT; s->dataHandler(s, 0, 0,SOPEN); } break; case tcp_StateESTAB: if ( (flags & tcp_FlagACK) == 0 ) return; /* process ack value in packet */ diff = lfix(tp->acknum) - s->seqnum; if ( diff > 0 ) { Move(&s->data[diff], &s->data[0], diff); s->dataSize -= diff; s->seqnum += diff; } s->flags = tcp_FlagACK; tcp_ProcessData(s, tp, len); break; case tcp_StateFINWT1: if ( (flags & tcp_FlagACK) == 0 ) return; diff = lfix(tp->acknum) - s->seqnum - 1; s->flags = tcp_FlagACK | tcp_FlagFIN; if ( diff == 0 ) { s->state = tcp_StateFINWT2; s->flags = tcp_FlagACK; }#ifdef FTP_SERVER_SUPPORT else { Move(&s->data[diff], &s->data[0], diff); s->dataSize -= diff; s->seqnum += diff; }#endif tcp_ProcessData(s, tp, len); break; case tcp_StateFINWT2: s->flags = tcp_FlagACK; tcp_ProcessData(s, tp, len); break; case tcp_StateCLOSING: if ( lfix(tp->acknum) == (s->seqnum + 1) ) { s->state = tcp_StateTIMEWT; s->timeout = tcp_TIMEOUT; } break; case tcp_StateLASTACK: if ( lfix(tp->acknum) == (s->seqnum + 1) ) { s->state = tcp_StateCLOSED; s->unhappy = FALSE; s->dataSize = 0; s->dataHandler(s, 0, 0,SCLOSE); tcp_Unthread(s); } else { s->flags = tcp_FlagACK | tcp_FlagFIN; tcp_Send(s); s->timeout = tcp_TIMEOUT; } break; case tcp_StateTIMEWT: s->flags = tcp_FlagACK; tcp_Send(s);#ifdef FTP_SERVER_SUPPORT s->state = tcp_StateCLOSED; s->dataHandler(s, 0, 0,SCLOSE); tcp_Unthread(s);#endif }}/* * Process the data in an incoming packet. * Called from all states where incoming data can be received: established, * fin-wait-1, fin-wait-2 */void tcp_ProcessData(tcp_Socket *s, tcp_Header *tp, int len){ int diff, x; word flags; byte *dp; flags = wfix(tp->flags); diff = s->acknum - lfix(tp->seqnum); if ( flags & tcp_FlagSYN ) diff--; x = tcp_GetDataOffset(tp) << 2; dp = (byte *)tp + x; len -= x; if ( diff >= 0 ) { dp += diff; len -= diff; s->acknum += len; s->dataHandler(s, dp, len,SDATA); if ( flags & tcp_FlagFIN ) { s->acknum++; switch(s->state) { case tcp_StateESTAB: /* note: skip state CLOSEWT by automatically closing conn */ x = tcp_StateLASTACK; s->flags |= tcp_FlagFIN; s->unhappy = TRUE; break; case tcp_StateFINWT1: x = tcp_StateCLOSING; break; case tcp_StateFINWT2: x = tcp_StateTIMEWT; break; } s->state = x; } tcp_Send(s); } s->timeout = tcp_TIMEOUT;}/* * Format and send an outgoing segment */void tcp_Send(tcp_Socket *s){ tcp_PseudoHeader ph; struct _pkt { in_Header in; tcp_Header tcp; longword maxsegopt; } *pkt; byte *dp; pkt = (struct _pkt *)sed_FormatPacket(&s->hisethaddr[0], 0x800); dp = (byte *)&pkt->maxsegopt; pkt->in.length = wfix(sizeof(in_Header) + sizeof(tcp_Header) + s->dataSize); /* tcp header */ pkt->tcp.srcPort = wfix(s->myport); pkt->tcp.dstPort = wfix(s->hisport); pkt->tcp.seqnum = lfix(s->seqnum); pkt->tcp.acknum = lfix(s->acknum); pkt->tcp.window = wfix(1024); pkt->tcp.flags = wfix(s->flags | 0x5000); pkt->tcp.checksum = 0; pkt->tcp.urgentPointer = 0; if ( s->flags & tcp_FlagSYN ) { pkt->tcp.flags = wfix(0x1000+wfix(pkt->tcp.flags)); pkt->in.length = wfix(4+wfix(pkt->in.length)); pkt->maxsegopt = lfix(0x02040578); /* 1400 bytes */ dp += 4; } MoveW(s->data, dp, s->dataSize); /* internet header */ pkt->in.vht = wfix(0x4500); /* version 4, hdrlen 5, tos 0 */ pkt->in.identification = wfix(tcp_id++); pkt->in.frag = 0; pkt->in.ttlProtocol = wfix((250<<8) + TCP_PROTO); pkt->in.checksum = 0; pkt->in.source = lfix(sin_lclINAddr); pkt->in.destination = lfix(s->hisaddr); pkt->in.checksum = wfix(~checksum(&pkt->in, sizeof(in_Header))); /* compute tcp checksum */ ph.src = pkt->in.source; ph.dst = pkt->in.destination; ph.mbz = 0; ph.protocol = TCP_PROTO; ph.length = wfix(wfix(pkt->in.length) - sizeof(in_Header)); ph.checksum = wfix(checksum(&pkt->tcp, wfix(ph.length))); pkt->tcp.checksum = wfix(~checksum(&ph, sizeof ph)); sed_Send(wfix(pkt->in.length));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -