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; }
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; }
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); }
/* *************************************************** * 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; }
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; }
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; }
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; }
/* 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; }
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; }
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; }
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 }