⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcp.c

📁 ppp拨号程序源代码采用atmel芯片c语言编
💻 C
📖 第 1 页 / 共 4 页
字号:
	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 + -