STATE filename(char *fname, int32_t buf_size) { uint8_t packet[MAX_LEN]; uint8_t buf[MAX_LEN]; uint8_t flag = 0; int32_t seq_num = 0; int32_t fname_len = strlen(fname) + 1; int32_t recv_check = 0; memcpy(buf, &buf_size, 4); memcpy(&buf[4], fname, fname_len); send_buf(buf, fname_len + 4, &server, FNAME, 0, packet); if (select_call(server.sk_num, 1, 0, NOT_NULL) == 1) { recv_check = recv_buf(packet, 1000, server.sk_num, &server, &flag, &seq_num); /* check for bit flip ... if so, send the file name again */ if (recv_check == CRC_ERROR) return FILENAME; if (flag == FNAME_BAD) { printf("File %s already exists and is write-protected\n", fname); return DONE; } return FILE_OK; } return FILENAME; }
STATE wait_on_ack() { static int32_t send_count = 0; uint32_t crc_check = 0; uint8_t buf[MAX_LEN]; int32_t len = 1000; uint8_t flag = 0; int32_t seq_num = 0; send_count++; if (send_count > 5) { printf("Sent data 5 times, no ACK, client session terminated\n"); return(DONE); } if (select_call(server.sk_num, 1, 0, NOT_NULL) != 1) { return (TIMEOUT_ON_ACK); } crc_check = recv_buf(buf, len, server.sk_num, &server, &flag, &seq_num); if (crc_check == CRC_ERROR) return WAIT_ON_ACK; if (flag != ACK) { printf("In wait_on_ack but its not an ACK flag (this should never happen) is: %d\n", flag); exit(-1); } /* ack is good so reset count and then go send some more data */ send_count = 0; return SEND_DATA; }
STATE recv_eof(Window *window, int output_fd) { uint8_t flag = 0; int32_t data_len = 0; uint8_t data_buf[MAX_PACKET_LEN]; uint32_t seq_num = nextOpenSequenceNumber(window); send_ack(seq_num); // Drain the packet queue while (select_call(server.socket_num, 1, 0, NOT_NULL) == 1) { data_len = recv_buf(data_buf, MAX_PACKET_LEN, server.socket_num, &server, &flag, &seq_num); return STATE_EOF; } printf("File Transfer Complete\n"); return STATE_DONE; }
/** * Receive the initial packet. * If no data is received, result = RES_NO_DATA and p_init_pkt is undefined; * Else if data is received but is corrupted, result = RES_DATA_CORRUPT; * Else if data is received but file cannot be opened, result = RES_FILE_ERR; * Else, data is received and check sum is verified, result = RES_SUCCESS, p_init_pkt contains init info * and file **/ int recv_init(int sock_num, struct sockaddr_in * p_cli_addr, init_pkt_t ** p_p_init_pkt, FILE ** p_p_file) { int result = RES_NO_DATA; //debug_max("--------- receive init packet (wait %i secs) ---------\n", SRV_WAIT_SECS); if (select_call(sock_num, SRV_WAIT_SECS, 0)) { /* Get the packet */ char * data_buff = malloc(MAX_INIT_PKT_SZ); recv_packet(sock_num, data_buff, MAX_INIT_PKT_SZ, p_cli_addr); //int bytes_trfd = recv_packet(sock_num, data_buff, MAX_INIT_PKT_SZ, p_cli_addr); //debug_max("recv_init(): bytes_trfd = %i\n", bytes_trfd); //print_bytes(data_buff, bytes_trfd); /* Parse the packet */ *p_p_init_pkt = unmarshall_init_pkt(data_buff); // Check to see if we're getting the handshake again if ((*p_p_init_pkt)->hdr.seq_num == HS_SEQ_NUM) { send_ack(sock_num, p_cli_addr, HS_SEQ_NUM, ACK_PKT_TYPE); } if ((*p_p_init_pkt)->hdr.chk_sum != 0) { //debug_min("recv_init(): p_init_pkt->hdr.chk_sum = %hu\n", (*p_p_init_pkt)->hdr.chk_sum); //print_sockaddr_info(p_cli_addr); // NAK the packet send_ack(sock_num, p_cli_addr, INIT_SEQ_NUM, NAK_PKT_TYPE); return RES_DATA_CORRUPT; } /* Try to open the file */ *p_p_file = fopen((*p_p_init_pkt)->filename, "w+"); if (*p_p_file == NULL) { perror("Could not open file for writing"); send_ack(sock_num, p_cli_addr, INIT_SEQ_NUM, FILE_ERR_PKT_TYPE); return RES_FILE_ERR; } /* Send positive acknowledgement */ send_ack(sock_num, p_cli_addr, INIT_SEQ_NUM, ACK_PKT_TYPE); result = RES_SUCCESS; //debug_max("recv_init(): result = %i\n", result); } else { //debug_medium("recv_int(): did not find any data to receive\n"); } return result; }
/** Identifies who is calling * * @return the uid of the person calling when successful, else 0 */ uint32_t UDP::getCallerID() { int status, rec_size; packet initPacket; status = select_call(&socket_num, 1, INIT_TIMEOUT, 0); if (status) { rec_size = recvfrom(socket_num, (void *) &initPacket, sizeof(packet), 0, (struct sockaddr *) &client_addr, &client_addr_len); if (rec_size == 0) { #ifdef DEBUG cerr << "getCallerID: socket_num shutdown\n"; #endif } else if (rec_size != sizeof(packet)) { perror("recv()"); } else { return ntohl(initPacket.uid); } } return 0; }
STATE filename(char *fname, int32_t buf_size, int32_t window_size) { uint8_t buf[MAX_PACKET_LEN]; uint8_t flag = 0; uint32_t seq_num = 0; int32_t fname_len = strlen(fname) + 1; int32_t recv_check = 0; buf_size = htonl(buf_size); memcpy(buf, &buf_size, 4); window_size = htonl(window_size); memcpy(&buf[4], &window_size, 4); memcpy(&buf[8], fname, fname_len); send_buf(buf, fname_len + 8, &server, FLAG_FILENAME_REQ, 0); if (select_call(server.socket_num, 1, 0, NOT_NULL) == 1) { recv_check = recv_buf(buf, MAX_PACKET_LEN, server.socket_num, &server, &flag, &seq_num); if (recv_check == CRC_ERROR) { return STATE_FILENAME; } switch (flag) { case FLAG_FILENAME_RESP_OK: return STATE_FILE_OK; break; case FLAG_FILENAME_RESP_BAD: printf("File (%s) not found on server\n", fname); exit(1); break; default: break; } } return STATE_FILENAME; }
int Client::recvPacket(packet &buf) { #ifndef DEBUG_CHLD // Check for timeout if (select_call(mvSocket, 1, 0) == 0) { std::cerr << "Server timed out. Retries left: " << mvRetries-- << std::endl; return 2; } mvRetries = PKT_TRNSMAX; #endif // Receive packets if (recvfrom(mvSocket, &buf, sizeof(packet), 0, (sockaddr *)&mvAddr, &mvAddrLen) == -1) { std::cerr << "recvfrom (" << __LINE__ << "): " << strerror(errno) << std::endl; return 1; } // Verify packet checksum uint16_t ck = buf.checksum; buf.checksum = 0; if ((buf.checksum = in_cksum((unsigned short*)&buf, sizeof(packet))) != ck) { std::cerr << "Received packet with bad checksum. Expected 0x" << std::hex << ck << ", received 0x" << std::hex << buf.checksum << std::endl << "Sequence: " << std::dec << buf.sequence << std::endl << "Retries left: " << std::dec << mvRetries-- << std::endl; return 2; } return 0; }
STATE recv_data(Window *window) { uint32_t seq_num = 0; uint8_t flag = 0; int32_t data_len = 0; uint8_t data_buf[MAX_PACKET_LEN]; uint32_t window_index; uint32_t buffer_offset; uint32_t next_seq_num; uint32_t max_seq_num; static uint32_t expected_seq_number = 0; if (select_call(server.socket_num, 10, 0, NOT_NULL) == 0) { fprintf(stderr, "Shutting down: No response from server for 10 seconds.\n"); exit(1); } data_len = recv_buf(data_buf, MAX_PACKET_LEN, server.socket_num, &server, &flag, &seq_num); if (data_len == CRC_ERROR) { return STATE_RECV_DATA; } switch (flag) { case FLAG_DATA: case FLAG_DATA_RESENT: max_seq_num = maxSequenceNumber(window); next_seq_num = nextOpenSequenceNumber(window); // printf("PACKET: seq_num: %u max: %u next: %u exp: %u\n", seq_num, max_seq_num, next_seq_num, expected_seq_number); if (seq_num < next_seq_num) { if (seq_num < window->base_seq_num) { send_ack(window->base_seq_num-1); } else { if (windowIsFull(window)) { send_ack(max_seq_num); } else { send_srej(next_seq_num); } } break; } // See if the seq_num falls within this windows range if ((seq_num >= window->base_seq_num) && (seq_num < (window->base_seq_num + window->window_size))) { window_index = (seq_num-1) % window->window_size; // Save data if it isn't already in there if (window->registry[window_index] == 0) { buffer_offset = window_index * window->block_size; memcpy(&window->buffer[buffer_offset], data_buf, data_len); // Mark the window as received window->registry[window_index] = 1; max_seq_num = maxSequenceNumber(window); next_seq_num = nextOpenSequenceNumber(window); if (seq_num == max_seq_num) { window->buffer_size = buffer_offset + data_len; } } } if (seq_num > next_seq_num) { // the previous sequence number window_index = ((seq_num-1) % window->window_size); if (window->registry[window_index-1] == 0) { send_srej(window->base_seq_num+window_index-1); } } else { send_ack(next_seq_num-1); } expected_seq_number = next_seq_num; if (windowIsFull(window)) { // printf("Window Full\n"); return STATE_WINDOW_FULL; } break; case FLAG_END_OF_FILE: // printf("GOT EOF: seq_num: %u\n", seq_num);// !!! return STATE_EOF; break; default: break; } return STATE_RECV_DATA; }
/** * Implement Go-Back-N sliding windows to receive the data packets. **/ void recv_file(int sock_num, struct sockaddr_in * p_cli_addr, u_int file_len, u_int buffer_sz, FILE * p_file) { u_int last_pkt_ackd = INIT_SEQ_NUM; u_int next_pkt = last_pkt_ackd + 1; u_int total_seqs = ((int) ceil((double) file_len / (double) buffer_sz)) + INIT_SEQ_NUM; //debug_max("------------- receive file -------------\n"); //debug_max("recv_file(): total_seqs = %i\n", total_seqs); /* Start receiving packets */ data_pkt_t * p_data_pkt = NULL; int i = 0; while (next_pkt <= total_seqs) { // we still have packets to receive i++; //debug_max("recv_file(): round = %i\n", i); //debug_max("recv_file(): next_pkt = %i <= total_seq = %i\n", next_pkt, total_seqs); if (select_call(sock_num, SRV_WAIT_SECS, 0)) { p_data_pkt = recv_data(sock_num, p_cli_addr); //debug_max("\trecv_file(): p_data_pkt->hdr.chk_sum = %i\n", p_data_pkt->hdr.chk_sum); //debug_max("\trecv_file(): p_data_pkt->hdr.seq_num = %i -v- next_pkt = %i\n", p_data_pkt->hdr.seq_num, next_pkt); if (p_data_pkt->hdr.chk_sum !=0 ) { // packet is corrupt, don't use //debug_max("\trecv_file(): check sum error\n"); send_ack(sock_num, p_cli_addr, next_pkt, NAK_PKT_TYPE); } else if (p_data_pkt->hdr.seq_num == next_pkt) { // this is the one we're looking for // check the check sum to decide what to do //debug_max("\trecv_file(): send ack seq_num = %i\n", p_data_pkt->hdr.seq_num); // packet is uncorrupted, write to file and ACK fwrite(p_data_pkt->data, sizeof(char), p_data_pkt->hdr.buffer_sz, p_file); send_ack(sock_num, p_cli_addr, p_data_pkt->hdr.seq_num, ACK_PKT_TYPE); last_pkt_ackd = p_data_pkt->hdr.seq_num; next_pkt = last_pkt_ackd + 1; } else if (p_data_pkt->hdr.seq_num == 1) { // catch the case where the init packet gets resent // and simply re-ACK send_ack(sock_num, p_cli_addr, INIT_PKT_TYPE, ACK_PKT_TYPE); } else if (p_data_pkt->hdr.seq_num < next_pkt) { // we've already seen, re-ack //debug_max("\t\trecv_file(): re-acking %i\n", p_data_pkt->hdr.seq_num); send_ack(sock_num, p_cli_addr, last_pkt_ackd, ACK_PKT_TYPE); } else { // too high, we must have missed one, NAK what we were looking for //debug_max("\t\trecv_file(): NAKing... p_data_pkt->hdr.chk_sum = %hu\n", p_data_pkt->hdr.chk_sum); send_ack(sock_num, p_cli_addr, next_pkt, NAK_PKT_TYPE); } } else { // heard nothing from the client debug_errors("recv_file(): heard nothing from client; exiting\n"); break; } } debug_print("recv_file(): finished receiving file from client\n"); }