#include "sysinclude.h"
extern void tcp_DiscardPkt(char* pBuffer, int type);
extern void tcp_sendReport(int type);
extern void tcp_sendIpPkt(unsigned char* pData, UINT16 len, unsigned int srcAddr, unsigned int dstAddr, UINT8 ttl);
extern int waitIpPacket(char *pBuffer, int timeout);
extern unsigned int getIpv4Address();
extern unsigned int getServerIpv4Address();
#define INPUT 0
#define OUTPUT 1
#define NOT_READY 0
#define READY 1
#define DATA_NOT_ACKED 0
#define DATA_ACKED 1
#define NOT_USED 0
#define USED 1
#define MAX_TCP_CONNECTIONS 5
#define INPUT_SEG 0
#define OUTPUT_SEG 1
typedef int STATE;
int gLocalPort = 2007;
int gRemotePort = 2006;
int gSeqNum = 1234;
int gAckNum = 0;
enum TCP_STATES
{
CLOSED,
SYN_SENT,
ESTABLISHED,
FIN_WAIT1,
FIN_WAIT2,
TIME_WAIT,
};
struct MyTcpSeg
{
unsigned short src_port;
unsigned short dst_port;
unsigned int seq_num;
unsigned int ack_num;
unsigned char hdr_len;
unsigned char flags;
unsigned short window_size;
unsigned short checksum;
unsigned short urg_ptr;
unsigned char data[2048];
unsigned short len;
};
struct MyTCB
{
STATE current_state;
unsigned int local_ip;
unsigned short local_port;
unsigned int remote_ip;
unsigned short remote_port;
unsigned int seq;
unsigned int ack;
unsigned char flags;
int iotype;
int is_used;
int data_ack;
unsigned char data[2048];
unsigned short data_len;
};
struct MyTCB gTCB[MAX_TCP_CONNECTIONS];
int initialized = NOT_READY;
int convert_tcp_hdr_ntoh(struct MyTcpSeg* pTcpSeg)
{
if( pTcpSeg == NULL )
{
return -1;
}
pTcpSeg->src_port = ntohs(pTcpSeg->src_port);
pTcpSeg->dst_port = ntohs(pTcpSeg->dst_port);
pTcpSeg->seq_num = ntohl(pTcpSeg->seq_num);
pTcpSeg->ack_num = ntohl(pTcpSeg->ack_num);
pTcpSeg->window_size = ntohs(pTcpSeg->window_size);
pTcpSeg->checksum = ntohs(pTcpSeg->checksum);
pTcpSeg->urg_ptr = ntohs(pTcpSeg->urg_ptr);
return 0;
}
int convert_tcp_hdr_hton(struct MyTcpSeg* pTcpSeg)
{
if( pTcpSeg == NULL )
{
return -1;
}
pTcpSeg->src_port = htons(pTcpSeg->src_port);
pTcpSeg->dst_port = htons(pTcpSeg->dst_port);
pTcpSeg->seq_num = htonl(pTcpSeg->seq_num);
pTcpSeg->ack_num = htonl(pTcpSeg->ack_num);
pTcpSeg->window_size = htons(pTcpSeg->window_size);
pTcpSeg->checksum = htons(pTcpSeg->checksum);
pTcpSeg->urg_ptr = htons(pTcpSeg->urg_ptr);
return 0;
}
unsigned short tcp_calc_checksum(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)
{
int i = 0;
int len = 0;
unsigned int sum = 0;
unsigned short* p = (unsigned short*)pTcpSeg;
if( pTcb == NULL || pTcpSeg == NULL )
{
return 0;
}
for( i=0; i<10; i++)
{
sum += p[i];
}
sum = sum - p[8] - p[6] + ntohs(p[6]);
//printf("1...sum =%.2x\n", sum );
if( (len = pTcpSeg->len) > 20 )
{
if( len % 2 == 1 )
{
pTcpSeg->data[len - 20] = 0;
len++;
}
for( i=10; i<len/2; i++ )
{
sum += ntohs(p[i]);
}
}
//printf("2...sum =%.2x\n", sum );
sum = sum + (unsigned short)(pTcb->local_ip>>16)
+ (unsigned short)(pTcb->local_ip&0xffff)
+ (unsigned short)(pTcb->remote_ip>>16)
+ (unsigned short)(pTcb->remote_ip&0xffff);
sum = sum + 6 + pTcpSeg->len;
sum = ( sum & 0xFFFF ) + ( sum >> 16 );
sum = ( sum & 0xFFFF ) + ( sum >> 16 );
return (unsigned short)(~sum);
}
int get_socket(unsigned short local_port, unsigned short remote_port)
{
int i = 1;
int sockfd = -1;
for( i=1; i<MAX_TCP_CONNECTIONS; i++ )
{
if( gTCB[i].is_used == USED
&& gTCB[i].local_port == local_port
&& gTCB[i].remote_port == remote_port )
{
sockfd = i;
break;
}
}
return sockfd;
}
int tcp_init(int sockfd)
{
if( gTCB[sockfd].is_used == USED )
{
return -1;
}
gTCB[sockfd].current_state = CLOSED;
gTCB[sockfd].local_ip = getIpv4Address();
gTCB[sockfd].local_port = gLocalPort + sockfd - 1;
//gTCB[sockfd].remote_ip = ntohl(getServerIpv4Address());
//gTCB[sockfd].remote_port = gDstPort;
gTCB[sockfd].seq = gSeqNum;
gTCB[sockfd].ack = gAckNum;
gTCB[sockfd].is_used = USED;
gTCB[sockfd].data_ack = DATA_ACKED;
return 0;
}
int tcp_construct_segment(struct MyTcpSeg* pTcpSeg, struct MyTCB* pTcb, unsigned short datalen, unsigned char* pData)
{
pTcpSeg->src_port = pTcb->local_port;
pTcpSeg->dst_port = pTcb->remote_port;
pTcpSeg->seq_num = pTcb->seq;
pTcpSeg->ack_num = pTcb->ack;
pTcpSeg->hdr_len = (unsigned char)(0x50);
pTcpSeg->flags = pTcb->flags;
pTcpSeg->window_size = 1024;
pTcpSeg->urg_ptr = 0;
if( datalen > 0 && pData != NULL )
{
memcpy(pTcpSeg->data, pData, datalen);
}
pTcpSeg->len = 20 + datalen;
return 0;
}
int tcp_kick(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)
{
pTcpSeg->checksum = tcp_calc_checksum(pTcb, pTcpSeg);
convert_tcp_hdr_hton(pTcpSeg);
tcp_sendIpPkt((unsigned char*)pTcpSeg, pTcpSeg->len, pTcb->local_ip, pTcb->remote_ip, 255);
//memcpy(&(pTcb->last_seg), pTcpSeg, pTcpSeg->len);
if( (pTcb->flags & 0x0f) == 0x00 )
{
//data
pTcb->seq += pTcpSeg->len - 20;
}
else if( (pTcb->flags & 0x0f) == 0x02 )
{
//syn
pTcb->seq++;
}
else if( (pTcb->flags & 0x0f) == 0x01 )
{
//fin
pTcb->seq++;
}
else if( (pTcb->flags & 0x3f) == 0x10 )
{
//ack
}
return 0;
}
int tcp_closed(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)
{
if( pTcb == NULL || pTcpSeg == NULL )
{
return -1;
}
if( pTcb->iotype != OUTPUT )
{
//to do: discard packet
return -1;
}
pTcb->current_state = SYN_SENT;
pTcb->seq = pTcpSeg->seq_num ;
tcp_kick( pTcb, pTcpSeg );
return 0;
}
int tcp_syn_sent(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)
{
struct MyTcpSeg my_seg;
if( pTcb == NULL || pTcpSeg == NULL )
{
return -1;
}
if( pTcb->iotype != INPUT )
{
return -1;
}
if( (pTcpSeg->flags & 0x3f) != 0x12 )
{
//to do: discard packet
return -1;
}
pTcb->ack = pTcpSeg->seq_num + 1;
pTcb->flags = 0x10;
tcp_construct_segment( &my_seg, pTcb, 0, NULL );
tcp_kick( pTcb, &my_seg );
pTcb->current_state = ESTABLISHED;
return 0;
}
int tcp_established(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)
{
struct MyTcpSeg my_seg;
if( pTcb == NULL || pTcpSeg == NULL )
{
return -1;
}
if( pTcb->iotype == INPUT )
{
if( pTcpSeg->seq_num != pTcb->ack )
{
tcp_DiscardPkt((char*)pTcpSeg, STUD_TCP_TEST_SEQNO_ERROR);
//to do: discard packet
return -1;
}
if( (pTcpSeg->flags & 0x3f) == 0x10 )
{
//get packet and ack it
memcpy(pTcb->data, pTcpSeg->data, pTcpSeg->len - 20);
pTcb->data_len = pTcpSeg->len - 20;
if( pTcb->data_len == 0 )
{
//pTcb->ack = pTcpSeg->seq_num + 1;
//pTcb->ack++;
}
else
{
pTcb->ack += pTcb->data_len;
pTcb->flags = 0x10;
tcp_construct_segment(&my_seg, pTcb, 0, NULL);
tcp_kick(pTcb, &my_seg);
}
}
}
else
{
if( (pTcpSeg->flags & 0x0F) == 0x01 )
{
pTcb->current_state = FIN_WAIT1;
}
tcp_kick( pTcb, pTcpSeg );
}
return 0;
}
int tcp_finwait_1(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)
{
if( pTcb == NULL || pTcpSeg == NULL )
{
return -1;
}
if( pTcb->iotype != INPUT )
{
return -1;
}
if( pTcpSeg->seq_num != pTcb->ack )
{
tcp_DiscardPkt((char*)pTcpSeg, STUD_TCP_TEST_SEQNO_ERROR);
return -1;
}
if( (pTcpSeg->flags & 0x3f) == 0x10 && pTcpSeg->ack_num == pTcb->seq )
{
pTcb->current_state = FIN_WAIT2;
//pTcb->ack++;
}
return 0;
}
int tcp_finwait_2(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)
{
struct MyTcpSeg my_seg;
if( pTcb == NULL || pTcpSeg == NULL )
{
return -1;
}
if( pTcb->iotype != INPUT )
{
return -1;
}
if( pTcpSeg->seq_num != pTcb->ack )
{
tcp_DiscardPkt((char*)pTcpSeg, STUD_TCP_TEST_SEQNO_ERROR);
return -1;
}
if( (pTcpSeg->flags & 0
评论0