📄 tcp.c
字号:
while (Socket->TxBufferWr >= sizeof(Socket->TxBuffer)) Socket->TxBufferWr -= sizeof(Socket->TxBuffer); //
//
return i; // number of bytes saved into the buffer
}
// ******************************************************************************************
bool TCP_StartPacket(T_TCP_Socket *Socket)
{ // start constructing a tcp packet for tranmission
if (MainBufferWr_Tx > 0) return false; // the buffer is in use
//
if (Socket == NULL) return false; //
//
IP_StartPacket(IP_PROTO_TCP, Socket->RemoteIP.ip32); // start the IP packet off
//
Socket->len = MainBufferWr_Tx; //
//
TCP_Header = (T_TCP_Header*)(MainBuffer + MainBufferWr_Tx); // point to the TCP header
memset(TCP_Header, 0, sizeof(T_TCP_Header)); // clear it
TCP_Header->DataOffset = sizeof(T_TCP_Header); //
TCP_Header->WindowSize = (u16)RingBufBytesFree(sizeof(Socket->RxBuffer), Socket->RxBufferRd, Socket->RxBufferWr); // number of bytes we have free in our rx buffer
//
MainBufferWr_Tx += sizeof(T_TCP_Header); // update index
//
return true; //
}
bool TCP_EndPacket(T_TCP_Socket *Socket)
{ // end constructing a tcp packet for tranmission and send it
u16 w, w2;
if (Socket == NULL) return false; //
//
if (TCP_Header->ControlBits & (TCP_SYN|TCP_FIN|TCP_PSH|TCP_RST)) //
{ //
u16_Put(&Socket->Retry_Timer, 0); //
Socket->Retries++; //
} //
//
TCP_Header->SourcePort = htons(Socket->LocalPort); //
TCP_Header->DestPort = htons(Socket->RemotePort); //
TCP_Header->SequenceNum = htonl(Socket->OurSequenceNum); //
TCP_Header->AckNum = htonl(Socket->TheirSequenceNum); //
TCP_Header->WindowSize = htons(TCP_Header->WindowSize); //
TCP_Header->UrgentPointer = htons(TCP_Header->UrgentPointer); //
TCP_Header->DataOffset >>= 2; //
TCP_Header->DataOffset <<= 4; //
//
Socket->len = MainBufferWr_Tx - Socket->len; //
//
w2 = MainBufferWr_Tx; //
//
IP_Header->TotalLength += Socket->len; // update the IP header
//
w = IP_Checksum2((char*)TCP_Header, Socket->len); // update the TCP header checksum
// if (!w) w = 0xffff; //
TCP_Header->Checksum = htons(w); //
//
IP_EndPacket(); //
//
if (!PPP_SendPacket(false)) return false; // send it
#ifdef Debug
IP_DisplayProtocol(true, (int)w2); //
IP_DisplayHeader(4, (int)w2); //
TCP_DisplayHeader(4 + sizeof(T_IP_Header), (int)w2); //
//
sprintf((char*)ScratchPad, "TxBufferRd:%d TxBufferWr:%d\n", Socket->TxBufferRd, Socket->TxBufferWr); //
SendDebugStr((char*)ScratchPad); //
#endif
//
return true; //
}
bool TCP_SendPacket(T_TCP_Socket *Socket, u8 ControlBits)
{ // construct a tcp packet and send it
int i, j;
if (!TCP_StartPacket(Socket)) return false; //
//
if (ControlBits & TCP_SYN) //
{ //
i = sizeof(MainBuffer); //
if (i > sizeof(Socket->RxBuffer)) i = sizeof(Socket->RxBuffer); //
i -= 50; // allow for headers etc
MainBuffer[MainBufferWr_Tx++] = 2; // type ... max segment size option
MainBuffer[MainBufferWr_Tx++] = 4; // length
*(u16*)(MainBuffer + MainBufferWr_Tx) = htons(i); // max seg size
MainBufferWr_Tx += 2; //
TCP_Header->DataOffset += 4; // Update TCP header
//
if ((Socket->Stage == TCP_CLOSED) || (Socket->Stage == TCP_LISTEN)) //
{ //
TCP_SocketStage(Socket, TCP_SYN_SENT); //
} //
} //
else //
if (Socket->Stage == TCP_ESTABLISHED) //
{ //
if ((ControlBits & TCP_ACK) && (Socket->TxBufferRd != Socket->TxBufferWr)) //
{ // send some data with the packet
i = RingBufBytes(sizeof(Socket->TxBuffer), Socket->TxBufferRd, Socket->TxBufferWr); // number of bytes waiting to go
if (i > Socket->TheirWindowSize) i = Socket->TheirWindowSize; //
//
j = sizeof(MainBuffer) - MainBufferWr_Tx; //
if (i > j) i = j; //
//
j = CopyFromRingBuffer(MainBuffer + MainBufferWr_Tx, Socket->TxBuffer, Socket->TxBufferRd, sizeof(Socket->TxBuffer), i); // move data from the tx buffer into the tx packet
//
if (j > 0) //
{ //
MainBufferWr_Tx += j; //
ControlBits |= TCP_PSH; //
Socket->OurLastBytesSent = j; //
} //
} //
} //
//
TCP_Header->ControlBits = ControlBits; // set the tx packet control bits
//
if (ControlBits & TCP_ACK) //
{ //
u16_Put(&Socket->AckDelay, TCP_AckDelay); //
Socket->SendAck = false; // ack has been sent
} //
//
return TCP_EndPacket(Socket); //
}
//*****************************************************************************************************
void TCP_In(void)
{ // this is called when we have rx'ed a tcp packet
u8 type;
int i;
u16 len;
u32 dw;
u16 MaxSegSize = 0;
T_TCP_Socket *Socket = NULL;
len = MainBufferWr_Rx - MainBufferRd_Rx; // length of data left
// *******************
// TCP header
TCP_Header = (T_TCP_Header*)(MainBuffer + MainBufferRd_Rx); // point to the TCP header
#ifdef Debug
TCP_DisplayHeader(MainBufferRd_Rx, MainBufferWr_Rx); //
#endif
i = TCP_Header->DataOffset >> 4; // header length in 32-bit dwords
i <<= 2; // header length in bytes
if (i < sizeof(T_TCP_Header)) return; // hmmmmm
if (i > len) return; // "
//
if ((!TCP_Header->Checksum) || (IP_Checksum2((char*)TCP_Header, len))) //
{ // invalid checksum
#ifdef Debug //
SendDebugRStr(tcp_str40); //
#endif //
return; //
} //
//
// *******************
// go thru the header options
i += MainBufferRd_Rx; // point to data (immediately follows the TCP header)
MainBufferRd_Rx += sizeof(T_TCP_Header); // update index - now pointing to TCP options (if any)
while (MainBufferRd_Rx < i) //
{ // go thru each IP header option
type = MainBuffer[MainBufferRd_Rx++]; // option type
if (type == 0) break; // end of options
if (type == 1) continue; // no length byte
//
len = (u16)MainBuffer[MainBufferRd_Rx++]; // option length
if (len < 2) len = 2; //
if (type == 2) //
{ //
MaxSegSize = ntohs(*(u16*)(MainBuffer + MainBufferRd_Rx)); // maximum segment size
} //
else //
{ // unknown option //
} //
MainBufferRd_Rx += (len - 2); // point to next option
} //
MainBufferRd_Rx = i; //
//
len = MainBufferWr_Rx - MainBufferRd_Rx; // number of data bytes in the tcp packet
// *******************
// only let the packet past this point if it's from the station we have a link too
// - or if we are in listen mode
if (IP_Header->DestIP.ip32 != PPP.OUR_IP.ip32) return; // ignore it, it's not for us
//
Socket = TCP_Socket; // we only have one at the moment
if (Socket == NULL) return; //
//
if (!Socket->LocalPort) return; //
if (ntohs(TCP_Header->DestPort) != Socket->LocalPort) return; // wrong port, drop it
//
if (Socket->Stage == TCP_CLOSED) goto RefuseConnection; // we aint expecting any packets, shuv off!
//
if (Socket->Stage == TCP_LISTEN) //
{ //
// if (IP_FireWalled()) //
// { //
// #ifdef Debug //
// SendDebugRStr(tcp_str21); //
// #endif //
// return; // firewalled
// } //
//
if (Socket->RemoteIP.ip32) //
{ // waiting for a particular ip to connect
if (IP_Header->SourceIP.ip32 != Socket->RemoteIP.ip32) goto RefuseConnection; // ignore it
} //
//
if (Socket->RemotePort) //
{ // only a particular source port is allowed
if (ntohs(TCP_Header->SourcePort) != Socket->RemotePort) goto RefuseConnection; // wrong port, drop it
} //
} //
else //
{ //
if (IP_Header->SourceIP.ip32 != Socket->RemoteIP.ip32) goto RefuseConnection; // wrong ip, sod em
if (ntohs(TCP_Header->SourcePort) != Socket->RemotePort) goto RefuseConnection; // wrong port, drop it
} //
//
Socket->Flags = 0; // this will be altered if a packet needs sending back
// *******************
// connection reset
if (TCP_Header->ControlBits & TCP_RST)
{
if (Socket->Stage != TCP_LISTEN) TCP_SocketStage(Socket, TCP_CLOSED);
return;
}
// *******************
// check to see if it's a connect request
if (TCP_Header->ControlBits & TCP_SYN)
{
if (TCP_Header->ControlBits & (TCP_RST | TCP_FIN))
{ // wot they trying to do ?
TCP_SocketStage(Socket, TCP_CLOSED);
return;
}
switch (Socket->Stage)
{
case TCP_LISTEN : Socket->Flags |= TCP_SYN;
case TCP_SYN_SENT : TCP_SocketStage(Socket, TCP_SYN_RECEIVED);
break;
case TCP_SYN_RECEIVED : break;
case TCP_ESTABLISHED : // hmmmm - something is wrong
TCP_SendPacket(Socket, TCP_ACK); // send a packet back
return;
default : return; // ignore it - for now
}
// accept the incoming connection request
Socket->RemoteIP.ip32 = IP_Header->SourceIP.ip32; // their IP
Socket->RemotePort = ntohs(TCP_Header->SourcePort); // their port
Socket->TheirWindowSize = ntohs(TCP_Header->WindowSize); // their window size (how much data we can tx)
Socket->TheirSequenceNum = ntohl(TCP_Header->SequenceNum) + 1; // their sequence number
Socket->TxBufferRd = 0; //
Socket->TxBufferWr = 0; //
Socket->RxBufferRd = 0; //
Socket->RxBufferWr = 0; //
if (MaxSegSize) Socket->TheirMaxSegSize = MaxSegSize; //
//
Socket->Flags |= TCP_ACK; // we need to send an ACK back
}
// *******************
// disconnect request
if (TCP_Header->ControlBits & TCP_FIN)
{
if (TCP_Header->ControlBits & (TCP_SYN | TCP_RST))
{ // wot they trying to do ?
TCP_SocketStage(Socket, TCP_CLOSED);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -