TCP_API接口函数实验

 

#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;  

     

enum TCP_STATES  

{  

    CLOSED,  

    SYN_SENT,  

    ESTABLISHED,  

    FIN_WAIT1,  

    FIN_WAIT2,  

    TIME_WAIT,  

}; 

 

int gLocalPort = 2007;  

int gRemotePort = 2006;  

int gSeqNum = 1234;  

int gAckNum = 0;  

  

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];//TCB??  

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) //??TCP?checksum 

{  

    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]);    

  

    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]);  

        }  

    }    

  

    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报文同时seq+=n

    {  

        //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 & 0x0f) == 0x01 )  

    {  

        pTcb->ack++;  

        pTcb->flags = 0x10;  

  

        tcp_construct_segment( &my_seg, pTcb, 0, NULL );  

        tcp_kick( pTcb, &my_seg );   

        pTcb->current_state = CLOSED;  

    }  

    else  

    {  

        //to do   

    }  

  

    return 0;  

}  

  

int tcp_time_wait(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)  

{  

    pTcb->current_state = CLOSED;  

    //to do   

  

    return 0;  

}  

  

int tcp_check(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)  

{  

    int i = 0;  

    int len = 0;  

    unsigned int sum = 0;  

    unsigned short* p = (unsigned short*)pTcpSeg;  

    unsigned short *pIp;  

    unsigned int myip1 = pTcb->local_ip;  

    unsigned int myip2 = pTcb->remote_ip;  

  

    if( pTcb == NULL || pTcpSeg == NULL )  

    {  

        return -1;  

    }  

  

    for( i=0; i<10; i++)  

    {  

        sum = sum + p[i];  

    }  

    sum = sum - p[6] + ntohs(p[6]);  

  

    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]);  

        }  

    }  

  

    sum = sum + (unsigned short)(myip1>>16)  

        + (unsigned short)(myip1&0xffff)  

        + (unsigned short)(myip2>>16)  

        + (unsigned short)(myip2&0xffff);  

    sum = sum + 6 + pTcpSeg->len;  

  

    sum = ( sum & 0xFFFF ) + ( sum >> 16 );  

    sum = ( sum & 0xFFFF ) + ( sum >> 16 );  

  

    if( (unsigned short)(~sum) != 0 )  

    {  

        // TODO:   

        printf("check sum error!\n");  

  

        return -1;  

        //return 0;   

    }  

    else  

    {  

        return 0;  

    }  

}  

  

int tcp_switch(struct MyTCB* pTcb, struct MyTcpSeg* pTcpSeg)  

{  

    int ret = 0;  

  

    printf("STATE: %d\n", pTcb->current_state);  

  

    switch(pTcb->current_state)  

    {  

    case CLOSED:  

        ret = tcp_closed(pTcb, pTcpSeg);  

        break;  

    case SYN_SENT:  

        ret = tcp_syn_sent(pTcb, pTcpSeg);  

        break;  

    case ESTABLISHED:  

        ret = tcp_established(pTcb, pTcpSeg);  

        break;  

    case FIN_WAIT1:  

        ret = tcp_finwait_1(pTcb, pTcpSeg);  

        break;  

    case FIN_WAIT2:  

        ret = tcp_finwait_2(pTcb, pTcpSeg);  

        break;  

    case TIME_WAIT:  

        ret = tcp_time_wait(pTcb, pTcpSeg);  

        break;  

    default:  

        ret = -1;  

        break;  

    }  

  

    return ret;  

}  

  

int stud_tcp_input(char* pBuffer, unsigned short len, unsigned int srcAddr, unsigned int dstAddr)  

{  

    //construct MyTcpSeg from buffer   

    struct MyTcpSeg tcp_seg;  

    int sockfd = -1;  

  

    //printf("Here len = %d\n", len);   

  

    if( len < 20 )  

    {  

        return -1;  

    }  

  

    if(initialized == NOT_READY)  

    {  

        tcp_init(1);  

        gTCB[1].remote_ip = getServerIpv4Address();  

        gTCB[1].remote_port = gRemotePort;  

        initialized = READY;  

    }  

  

    memcpy(&tcp_seg, pBuffer, len);  

  

    tcp_seg.len = len;  

  

    //convert bytes' order   

    convert_tcp_hdr_ntoh(&tcp_seg);  

  

    sockfd = get_socket(tcp_seg.dst_port, tcp_seg.src_port);  

  

    if( sockfd == -1 || gTCB[sockfd].local_ip != ntohl(dstAddr) || gTCB[sockfd].remote_ip != ntohl(srcAddr) )  

    {  

        printf("sock error in stud_tcp_input()\n");  

        return -1;  

    }  

  

    //gTCB.local_ip = ntohl(dstAddr);   

    //gTCB.remote_ip = ntohl(srcAddr);   

  

    //check TCP checksum   

    if( tcp_check(&gTCB[sockfd], &tcp_seg) != 0 )  

    {  

        return -1;  

    }  

  

    gTCB[sockfd].iotype = INPUT;  

    memcpy(gTCB[sockfd].data,tcp_seg.data,len - 20);  

    gTCB[sockfd].data_len = len - 20;  

  

    tcp_switch(&gTCB[sockfd], &tcp_seg);  

  

    return 0;  

}  

  

void stud_tcp_output(char* pData, unsigned short len, unsigned char flag, unsigned short srcPort, unsigned short dstPort, unsigned int srcAddr, unsigned int dstAddr)  

{  

    struct MyTcpSeg my_seg;  

    int sockfd = -1;  

  

    if(initialized == NOT_READY)  

    {  

        tcp_init(1);  

        gTCB[1].remote_ip = getServerIpv4Address();  

        gTCB[1].remote_port = gRemotePort;  

        initialized = READY;  

    }  

  

    sockfd = get_socket(srcPort, dstPort);  

  

    if( sockfd == -1 || gTCB[sockfd].local_ip != srcAddr || gTCB[sockfd].remote_ip != dstAddr )  

    {  

        return;  

    }  

  

    gTCB[sockfd].flags = flag;  

    //gTCB.local_port = srcPort;   

    //gTCB.local_ip = ntohl(srcAddr);   

    //gTCB.remote_port = dstPort;   

    //gTCB.remote_ip = ntohl(dstAddr);   

  

    tcp_construct_segment(&my_seg, &gTCB[sockfd], len, (unsigned char *)pData);  

  

    gTCB[sockfd].iotype = OUTPUT;  

  

    tcp_switch(&gTCB[sockfd], &my_seg);  

}  

  

int stud_tcp_socket(int domain, int type, int protocol)  

{  

    int i = 1;  

    int sockfd = -1;  

  

    if( domain != AF_INET || type != SOCK_STREAM || protocol != IPPROTO_TCP )  

    {  

        return -1;  

    }  

  

    for( i=1; i<MAX_TCP_CONNECTIONS; i++ )  

    {  

        if( gTCB[i].is_used == NOT_USED )  

        {  

            sockfd = i;  

  

            if( tcp_init(sockfd) == -1 )  

            {  

                return -1;  

            }  

  

            break;  

        }  

    }  

  

    initialized = READY;  

  

    return sockfd;  

}  

  

int stud_tcp_connect(int sockfd, struct sockaddr_in* addr, int addrlen)  

{  

    char buffer[2048];  

    int len;  

  

    gTCB[sockfd].remote_ip = ntohl(addr->sin_addr.s_addr);  

    gTCB[sockfd].remote_port = ntohs(addr->sin_port);  

  

    stud_tcp_output( NULL, 0, 0x02, gTCB[sockfd].local_port, gTCB[sockfd].remote_port, gTCB[sockfd].local_ip, gTCB[sockfd].remote_ip );  

  

    len = waitIpPacket(buffer, 10);  

  

    if( len < 20 )  

    {  

        return -1;  

    }  

  

    if (stud_tcp_input(buffer, len, htonl(gTCB[sockfd].remote_ip), htonl(gTCB[sockfd].local_ip)) != 0){  

        return 1;  

    }  

    else  

    {  

        return 0;  

    }  

}   

  

int stud_tcp_send(int sockfd, const unsigned char* pData, unsigned short datalen, int flags)  

{  

    char buffer[2048];  

    int len;  

  

    if( gTCB[sockfd].current_state != ESTABLISHED )  

    {  

        return -1;  

    }  

  

    stud_tcp_output((char *)pData, datalen, flags, gTCB[sockfd].local_port, gTCB[sockfd].remote_port, gTCB[sockfd].local_ip, gTCB[sockfd].remote_ip);  

  

    len = waitIpPacket(buffer, 10);  

  

    if( len < 20 )  

    {  

        return -1;  

    }   

  

    stud_tcp_input(buffer, len, htonl(gTCB[sockfd].remote_ip), htonl(gTCB[sockfd].local_ip));  

  

    return 0;  

}  

  

int stud_tcp_recv(int sockfd, unsigned char* pData, unsigned short datalen, int flags)  

{  

    char buffer[2048];  

    int len;  

  

    if( (len = waitIpPacket(buffer, 10)) < 20 )  

    {  

        return -1;  

    }  

  

    stud_tcp_input(buffer, len,  htonl(gTCB[sockfd].remote_ip),htonl(gTCB[sockfd].local_ip));  

  

    memcpy(pData, gTCB[sockfd].data, gTCB[sockfd].data_len);  

  

    return gTCB[sockfd].data_len;  

}  

  

int stud_tcp_close(int sockfd)  

{  

    char buffer[2048];  

    int len;  

  

    stud_tcp_output(NULL, 0, 0x11, gTCB[sockfd].local_port, gTCB[sockfd].remote_port, gTCB[sockfd].local_ip, gTCB[sockfd].remote_ip);  

  

    //recv ACK   

    if( (len = waitIpPacket(buffer, 10)) < 20 )  

    {  

        return -1;  

    }  

  

    stud_tcp_input(buffer, len, htonl(gTCB[sockfd].remote_ip), htonl(gTCB[sockfd].local_ip));  

  

    //recv FIN   

    if( (len = waitIpPacket(buffer, 10)) < 20 )  

    {  

        return -1;  

    }  

  

    stud_tcp_input(buffer, len, htonl(gTCB[sockfd].remote_ip), htonl(gTCB[sockfd].local_ip));  

  

    gTCB[sockfd].is_used = NOT_USED;  

  

    return 0;  

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值