示例#1
0
int handle_cstate_fin_wait_2(mysocket_t sd, context_t * ctx){
    int ret = 0;
    unsigned int event;

    our_dprintf("in CSTATE_FIN_WAIT_2\n");
    event = stcp_wait_for_event(sd, NETWORK_DATA | TIMEOUT, NULL);

    /* check whether it was the network, app, or a close request */


    uint8_t buff[MAX_WINDOW_SIZE + sizeof(struct tcphdr)];
    if (event & NETWORK_DATA) {
        /* there was network data received */

        size_t recd;
        recd = stcp_network_recv(sd, buff, MAX_WINDOW_SIZE);
        if (recd == 0) {
            our_dprintf("bad network recv\n");
            return -1;
        }

        struct tcphdr * tcp_packet = (struct tcphdr *) buff;

        if (tcp_packet->th_flags & TH_FIN){
            /*  if fin */
            ctx->recd_last_byte_recd++;
            ctx->recd_last_byte_read++;
            ctx->recd_next_byte_expected++;
            send_syn_ack_fin(sd, ctx, SEND_ACK, 0, ctx->recd_next_byte_expected);
            ctx->connection_state = CSTATE_TIME_WAIT;
        }

    } 
    return ret;    
}
示例#2
0
int handle_cstate_fin_wait_1(mysocket_t sd, context_t * ctx){
    int ret = 0;
    unsigned int event;

    our_dprintf("in CSTATE_FIN_WAIT_1\n");
    event = stcp_wait_for_event(sd, NETWORK_DATA | TIMEOUT, NULL);

    /* check whether it was the network, app, or a close request */

    uint8_t buff[MAX_WINDOW_SIZE + sizeof(struct tcphdr)];
    if (event & NETWORK_DATA) {
        /* there was network data received */

        size_t recd;
        recd = stcp_network_recv(sd, buff, MAX_WINDOW_SIZE);
        if (recd == 0) {
            our_dprintf("bad network recv\n");
            return -1;
        }

        struct tcphdr * tcp_packet  = (struct tcphdr *) buff;

        if (tcp_packet->th_flags & (TH_ACK | TH_FIN)) {
            /* if ack + fin */
            if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){
                our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack);
                return -1;
            }
            ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack);
            ctx->recd_last_byte_recd++;
            ctx->recd_last_byte_read++;
            ctx->recd_next_byte_expected++;
            send_syn_ack_fin(sd, ctx, SEND_ACK, 0, ctx->recd_next_byte_expected);
            ctx->connection_state = CSTATE_TIME_WAIT;
        } else if (tcp_packet->th_flags & TH_ACK){
            /* ack received */
            if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){
                
                our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack);
                return -1;
            }
            ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack);
            //our_dprintf("*** got an ack %u\n", ctx->sent_last_byte_acked);
            ctx->connection_state = CSTATE_FIN_WAIT_2;

        } else if (tcp_packet->th_flags &  TH_FIN){
        /* else if fin */
            ctx->recd_last_byte_recd++;
            ctx->recd_last_byte_read++;
            ctx->recd_next_byte_expected++;
            send_syn_ack_fin(sd, ctx, SEND_ACK, 0, ctx->recd_next_byte_expected);
            ctx->connection_state = CSTATE_CLOSING;
        }

    } 

    return ret;    
}
示例#3
0
static int transport_recv_head(mysocket_t sd, void* headbuf, int headlen)//LAN
{
    //use ntohl ntohs decode related header
    ssize_t result = stcp_network_recv(sd, headbuf, sizeof(struct tcphdr), NULL);
    headbuf.th_seq = ntohs(head.th_seq);
    headbuf.th_ack = ntohs(head.th_ack);
    headbuf.th_win = ntohs(head.th_win);
    return sizeof(headbuf);
}
示例#4
0
/* ***************************************************
 * Function: network_recv
 * ***************************************************
 * Wrapper function for receiving network data.  It converts
 * data in the headers into host byte order.
 */
ssize_t network_recv(mysocket_t sd, void *dst)
{
	ssize_t result;
	/* Receive up to 44 bytes of TCP options */
	while ((result = stcp_network_recv(sd, dst, 
		   (TH_MAX_OFFSET*sizeof(uint32_t)) + STCP_MSS))<0);
	struct tcphdr* hdr = (struct tcphdr *)dst;
	hdr->th_ack = ntohl(hdr->th_ack);
	hdr->th_seq = ntohl(hdr->th_seq);
	hdr->th_win = ntohs(hdr->th_win);
	return result;	
}
示例#5
0
int handle_cstate_listen(mysocket_t sd, context_t * ctx) {
    int ret = 0;
    unsigned int event;

    our_dprintf("in CSTATE_LISTEN\n");
    
    event = stcp_wait_for_event(sd, ANY_EVENT, NULL);

    /* check whether it was the network, app, or a close request */

    if (event & NETWORK_DATA) {
        /* there was network data received */

        size_t recd;
        recd = stcp_network_recv(sd, ctx->recv_wind, MAX_WINDOW_SIZE);
        if (recd == 0) {
            our_dprintf("bad network recv\n");
            return -1;
        }
        struct tcphdr * tcp_packet  = (struct tcphdr *) ctx->recv_wind;
        //size_t recd_app = recd - 4 * tcp_packet->th_off;
        if (tcp_packet->th_flags & TH_SYN){
            /* syn received */
            ctx->initial_recd_seq_num = ntohl(tcp_packet->th_seq); 
            ctx->recd_last_byte_recd = ctx->initial_recd_seq_num;
            ctx->recd_next_byte_expected = ctx->recd_last_byte_recd + 1;
            ctx->recd_adv_window = ntohs(tcp_packet->th_win);
            send_syn_ack_fin(sd, ctx, SEND_SYN | SEND_ACK, 
                ctx->initial_sequence_num, ctx->recd_next_byte_expected);
            ctx->connection_state = CSTATE_SYN_RCVD;
        }
    } 
    if (event & APP_DATA) {
        /* the application has requested that data be sent */
        send_syn_ack_fin(sd, ctx, SEND_SYN, ctx->initial_sequence_num, 0);
        ctx->connection_state = CSTATE_SYN_SENT;
    } 

    if (event & APP_CLOSE_REQUESTED) {
        /* the application has requested that the conn be closed */
        ctx->connection_state = CSTATE_CLOSED;
    } 
    return ret;
}
示例#6
0
int handle_cstate_syn_rcvd(mysocket_t sd, context_t * ctx) {

    int ret = 0;
    unsigned int event;

    our_dprintf("in CSTATE_SYN_RCVD\n");
    event = stcp_wait_for_event(sd, NETWORK_DATA | APP_CLOSE_REQUESTED | TIMEOUT, NULL);

    /* check whether it was the network, app, or a close request */
    if (event & NETWORK_DATA) {
        /* there was network data received */

        size_t recd;
        recd = stcp_network_recv(sd, ctx->recv_wind, MAX_WINDOW_SIZE);
        if (recd == 0) {
            our_dprintf("bad network recv\n");
            return -1;
        }

        struct tcphdr * tcp_packet  = (struct tcphdr *) ctx->recv_wind;

        if (tcp_packet->th_flags & TH_ACK){
            /* ack received */
            if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){
                our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack);
                return -1;
            }
            ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack);
            ctx->recd_adv_window = ntohs(tcp_packet->th_win);
            //our_dprintf("*** got ack %u, got adv window %u\n", ctx->sent_last_byte_acked, ctx->recd_adv_window);
            ctx->connection_state = CSTATE_ESTABLISHED;
        }
    } 

    if (event & APP_CLOSE_REQUESTED) {
        /* the application has requested that the conn be closed */

        ctx->connection_state = CSTATE_FIN_WAIT_1;
        close_tcp_conn(sd, ctx);
    } 
    return ret;
}
示例#7
0
int handle_cstate_last_ack(mysocket_t sd, context_t * ctx){
    int ret = 0;

    unsigned int event;
    our_dprintf("in CSTATE_LAST_ACK\n");
    event = stcp_wait_for_event(sd, NETWORK_DATA | TIMEOUT, NULL);

    /* check whether it was the network, app, or a close request */

    uint8_t buff[MAX_WINDOW_SIZE + sizeof(struct tcphdr)];
    if (event & NETWORK_DATA) {
        /* there was network data received */

        size_t recd;
        recd = stcp_network_recv(sd, buff, MAX_WINDOW_SIZE);
        if (recd == 0) {
            our_dprintf("bad network recv\n");
            return -1;
        }

        struct tcphdr * tcp_packet  = (struct tcphdr *) buff;

        if (tcp_packet->th_flags & TH_ACK){
            /*  if ack */
            if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){
                our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack);
                return -1;
            }
            //our_dprintf("*** got an ack %u\n", ctx->sent_last_byte_acked);
            ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack);
            ctx->connection_state = CSTATE_CLOSED;

        }

    } 
    return ret;    
}
示例#8
0
/* call stcp_network_recv, error-check, update context, return packet header in header and payload in recvbuff. Return value is size of payload*/
int recv_packet(mysocket_t sd, context_t *ctx, void *recvbuff, size_t buffsize, STCPHeader *header) {
    size_t packlen, paylen, send_win;
    void *payload;
    void *buff = calloc(1, sizeof(STCPHeader) + MAXOPS + MAXLEN);
    size_t recv_window_size;
    int data_to_app = 0;

    /* zero out recvbuff and header so we're extra-sure there's no harm in re-using them */
    memset(recvbuff, '\0', buffsize);
    memset(header, '\0', sizeof(STCPHeader));

    /* receive data from network */
    packlen = stcp_network_recv(sd, buff, sizeof(STCPHeader) + MAXOPS + MAXLEN);
    if (packlen >= sizeof(STCPHeader)) {

        /* get packet header */
        memcpy(header, buff, sizeof(STCPHeader));
        DEBUG("Received packet with ack number %d (if TH_ACK set) and seq number %d\n", ntohl(header->th_ack), ntohl(header->th_seq));

        paylen = packlen - (WORDSIZE * header->th_off);
        if (paylen > 0) {
            /* update context recv buffer */
            int buffer_offset = ntohl(header->th_seq) - ctx->recv_next;

            payload = buff + (WORDSIZE * header->th_off);
            if (buffer_offset < 0) {
                buffer_offset = 0;
                if (ntohl(header->th_seq) + paylen <= ctx->recv_next) {
                    paylen = 0;
                    data_to_app = -2;
                }
                else {
                    payload += ctx->recv_next - ntohl(header->th_seq);
                    paylen -= ctx->recv_next - ntohl(header->th_seq);
                }
            }
            else if (buffer_offset > WINLEN) {
                free(buff);
                return -1;
            }

            recv_window_size = WINLEN - buffer_offset;
            if (paylen > recv_window_size) {
                paylen = recv_window_size;
                DEBUG("Packet crossed received window, was truncated\n");
            }

            memcpy(ctx->recv_buffer + buffer_offset, payload, paylen);
            memset(ctx->recv_indicator + buffer_offset, '1', paylen);

            /* update recv_next */
            ctx->recv_next += strchr(ctx->recv_indicator, '\0') - ctx->recv_indicator;

            if (data_to_app != -2)
                data_to_app = strchr(ctx->recv_indicator, '\0') - ctx->recv_indicator;
        }
        else
            data_to_app = 0;


        /* if packet acknowledges previously unacknowledged data, update send_unack */
        if ((header->th_flags & TH_ACK) && ctx->send_unack <= ntohl(header->th_ack))
            ctx->send_unack = ntohl(header->th_ack);

        /* update list of unack'd packets */
        packet_t_remove(ctx);

        /* if packet is a SYN, set ctx->recv_next, even though it doesn't include new data */
        if (header->th_flags & TH_SYN)
            ctx->recv_next = ntohl(header->th_seq) + 1;

        /* also update sender window size */
        send_win = ntohs(header->th_win); /* advertised sender window minus data still in transit to sender */
        if (send_win <= WINLEN)
            ctx->send_wind = send_win;
        else
            ctx->send_wind = WINLEN;
    }
    else {
        DEBUG("Error: invalid packet length");
        free (buff);
        return -1;
    }

    free(buff);
    return data_to_app;
}
示例#9
0
int handle_cstate_est_recv(mysocket_t sd, context_t * ctx){

    our_dprintf("* IN EST REC\n");
    size_t len =  sizeof(struct tcphdr) + STCP_MSS;
    uint8_t buff[len];
    uint32_t data_len, data_index;
    size_t delta, recv_len, recv_packet_len;
    recv_len = stcp_network_recv(sd, buff, len);
    struct tcphdr * tcp_packet  = (struct tcphdr *) buff;
    size_t hdr_size = tcp_packet->th_off * 4;
    recv_packet_len = recv_len - 4 * tcp_packet->th_off;

    /* check if any data was ack'd */
    if (tcp_packet->th_flags & TH_ACK) {
        if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){
            our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack);
            return -1;
        }
        ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack);
        //our_dprintf("****got an ack: %u\n", tcp_packet->th_ack);
    }
    /* check to see if the seq number is appropriate */
    if (ntohl(tcp_packet->th_seq) != ctx->recd_next_byte_expected){
        //our_dprintf("unexpected seq. rec seq : %u, expected : %u\n", tcp_packet->th_seq, ctx->recd_next_byte_expected);

        /* if part of the data is below the seq window */
        if ((ntohl(tcp_packet->th_seq) < ctx->recd_next_byte_expected) && 
            (ntohl(tcp_packet->th_seq) + recv_packet_len > ctx->recd_next_byte_expected)){
            //our_dprintf("some data salvageable\n");
            /* some of the data should be salvaged */
            data_len = ntohl(tcp_packet->th_seq) + recv_packet_len - ctx->recd_next_byte_expected;
            data_index = recv_packet_len - data_len;
        } else if (0) {
            /* placeholder for if data overflows upper bound of sliding window */

        } else {
            //our_dprintf("bad packet\n");
            return 0;
        }
    } else {
        data_len = recv_packet_len;
        data_index = 0;
    }
    uint8_t * data = buff + hdr_size; 
    uint32_t wind_index = ((ctx->recd_last_byte_recd + 1) - ctx->initial_recd_seq_num) % MAX_WINDOW_SIZE;  
    //our_dprintf("window index %u, data len %u\n", wind_index, data_len); 
    //our_dprintf("received data: %s\n", data);
    if (wind_index + data_len > MAX_WINDOW_SIZE){
        /* we're wrapping the buffer */
        delta = MAX_WINDOW_SIZE - wind_index;
        //our_dprintf("wrapping recv buff \n");
        /*copy data to ctx->buffer and send it to app */ 
        memcpy(ctx->recv_wind + wind_index, data + data_index, delta); 
        stcp_app_send( sd, ctx->recv_wind + wind_index, delta);

        memcpy(ctx->recv_wind, data + delta + data_index, data_len - delta);
        stcp_app_send( sd, ctx->recv_wind, data_len - delta);
        
    } else {
        /* we're not wrapping the buffer */
        //our_dprintf("don't need to wrap, data len %d\n", data_len);
        /*copy data to ctx->buffer and send it to app */
        memcpy(ctx->recv_wind + wind_index, data + data_index, data_len);
        stcp_app_send( sd, ctx->recv_wind + wind_index, data_len);
    }

    ctx->recd_last_byte_recd += data_len;
    ctx->recd_next_byte_expected += data_len;
    ctx->recd_last_byte_read += data_len;

    if (data_len > 0 ) {
        //our_dprintf("acking %u bytes\n", data_len);
        send_syn_ack_fin(sd, ctx, SEND_ACK, 0, ctx->recd_next_byte_expected);
    } else {
        //our_dprintf("** flags %u\n", tcp_packet->th_flags);
    }
    

    if (tcp_packet->th_flags & TH_FIN) {
        stcp_fin_received(sd);
        if (data_len == 0){
            ctx->recd_last_byte_recd++;
            ctx->recd_next_byte_expected++;
            ctx->recd_last_byte_read++;
        }
        send_syn_ack_fin(sd, ctx, SEND_ACK, 0, ctx->recd_next_byte_expected);
        ctx->connection_state = CSTATE_CLOSE_WAIT;
        close_tcp_conn(sd, ctx);
    }
    return 0;
}
示例#10
0
int handle_cstate_syn_sent(mysocket_t sd, context_t * ctx) {

    int ret = 0;
    unsigned int event;
    
    
    our_dprintf("in CSTATE_SYN_SENT\n");
    event = stcp_wait_for_event(sd, NETWORK_DATA | APP_CLOSE_REQUESTED | TIMEOUT, NULL);

    /* check whether it was the network, app, or a close request */
    if (event & NETWORK_DATA) {
        /* there was network data received */

        size_t recd, recd_app;
        recd = stcp_network_recv(sd, ctx->recv_wind, MAX_WINDOW_SIZE);
        if (recd == 0) {
            our_dprintf("bad network recv\n");
            return -1;
        }

        struct tcphdr * tcp_packet  = (struct tcphdr *) ctx->recv_wind;
        recd_app = recd - 4 * tcp_packet->th_off;
        /* if syn + ack */
        if (tcp_packet->th_flags & (TH_SYN | TH_ACK)) {
            if (ntohl(tcp_packet->th_ack) < ctx->sent_last_byte_acked || ntohl(tcp_packet->th_ack) > ctx->sent_last_byte_written+1){
                our_dprintf("bad ack, expected %u, received %u. returning \n", ctx->sent_last_byte_sent+1, tcp_packet->th_ack);
                return -1;
            }
            ctx->recd_adv_window = ntohs(tcp_packet->th_win);
            ctx->initial_recd_seq_num = ntohl(tcp_packet->th_seq);
            ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack);
            ctx->recd_last_byte_recd = ntohl(tcp_packet->th_seq);
            //our_dprintf("*** got ack %u, got adv win 3 = %u\n",ctx->sent_last_byte_acked ,ctx->recd_adv_window);
            ctx->recd_next_byte_expected = ctx->recd_last_byte_recd + 1;
            ctx->connection_state = CSTATE_ESTABLISHED;
            send_syn_ack_fin(sd, ctx, SEND_ACK, 0, 
                ctx->recd_next_byte_expected);

        /* else if syn */
        } else if (tcp_packet->th_flags & TH_SYN){
            /* syn received */
            ctx->initial_recd_seq_num = ntohl(tcp_packet->th_seq);
            ctx->recd_last_byte_recd = ntohl(tcp_packet->th_seq);
            ctx->recd_next_byte_expected = ctx->recd_last_byte_recd + 1;
            send_syn_ack_fin(sd, ctx, SEND_SYN | SEND_ACK, 
                ctx->initial_sequence_num, ctx->recd_next_byte_expected);
            ctx->recd_adv_window = ntohs(tcp_packet->th_win);

            if(tcp_packet->th_flags & TH_ACK){
                ctx->sent_last_byte_acked = ntohl(tcp_packet->th_ack);
            }
            ctx->connection_state = CSTATE_SYN_RCVD;
        }

    } 
    if (event & APP_CLOSE_REQUESTED) {
        /* the application has requested that the conn be closed */
        ctx->connection_state = CSTATE_CLOSED;
    } 
    return ret;
}
示例#11
0
static int transport_recv_data(mysocket_t sd, void* buf, int headlen)//LAN
{
    ssize_t result = stcp_network_recv(sd, recv_buffer, sizeof(recv_buffer), NULL);
    return result;//returns the actual amount of data read into recv_buffer
    //send real app data or stub data 
}