void send_ack(u_short seq) { packet_t ack_p; if (simulate_lag(delay_p)) { printf("packet %u delayed\n",seq); insert_dh(seq); } else { make_ack(seq, &ack_p); if (delay_p != 0) { traverse_dh(); } sendto(sock,(void *)&ack_p,PACKET_SIZE,0, (struct sockaddr *)(&src_addr),sizeof(src_addr)); printf("send ack seq %u to %s:%d\n", seq+1,inet_ntoa(src_addr.sin_addr),ntohs(src_addr.sin_port)); } }
static void ict_on_response(belle_sip_ict_t *obj, belle_sip_response_t *resp){ belle_sip_transaction_t *base=(belle_sip_transaction_t*)obj; int code=belle_sip_response_get_status_code(resp); const belle_sip_timer_config_t *cfg=belle_sip_transaction_get_timer_config(base); switch (base->state){ case BELLE_SIP_TRANSACTION_CALLING: belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_PROCEEDING); /* no break*/ case BELLE_SIP_TRANSACTION_PROCEEDING: if (code>=300){ belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_COMPLETED); belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)make_ack(obj,resp)); belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp); obj->timer_D=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_D,obj,cfg->T1*64); belle_sip_transaction_start_timer(base,obj->timer_D); }else if (code>=200){ obj->timer_M=belle_sip_timeout_source_new((belle_sip_source_func_t)ict_on_timer_M,obj,cfg->T1*64); belle_sip_transaction_start_timer(base,obj->timer_M); belle_sip_transaction_set_state(base,BELLE_SIP_TRANSACTION_ACCEPTED); belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp); }else if (code>=100){ belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp); } break; case BELLE_SIP_TRANSACTION_ACCEPTED: if (code>=200 && code<300){ belle_sip_client_transaction_notify_response((belle_sip_client_transaction_t*)obj,resp); } break; case BELLE_SIP_TRANSACTION_COMPLETED: if (code>=300 && obj->ack){ belle_sip_channel_queue_message(base->channel,(belle_sip_message_t*)obj->ack); } break; default: break; } }
void traverse_dh() { struct timeval current, diff; struct delay_node *p; p = DELAY_HEAD; packet_t ack_p; while (p->next!=NULL) { gettimeofday(¤t, NULL); timersubtract(diff,p->next->tv,current); if (diff.tv_sec < 0) { make_ack(p->next->seq, &ack_p); printf("send ack sequence number %u\n",ack_p.header.ack); sendto(sock,(void *)&ack_p,PACKET_SIZE,0, (struct sockaddr *)(&src_addr),sizeof(src_addr)); struct delay_node *q; q = p->next; p->next = q->next; free(q); } else { p = p->next; } } }
int main(int argc, char **argv) { if (argc < 2) { printf("Usage:\n"); printf(" %s port_no [loss_rate]\n", argv[0]); exit(1); } // Seed the RNG from is_lost() srand48(12345); // Parse/validate args char *port = argv[1]; printf("port = %s\n", port); long int x = strtol(argv[1], NULL, 10); if (x < 0 || x > USHRT_MAX) { fprintf(stderr, "[error]: port %ld is invalid\n", x); exit(1); } double loss_rate = 0.0; if (argc == 3) { loss_rate = strtof(argv[2], NULL); if (loss_rate < 0.0 || loss_rate > 1.0) { fprintf(stderr, "[error]: loss_rate must be between 0 and 1\n"); exit(1); } } // Get a socket to connect to int sock; struct sockaddr their_addr; if (get_addr_sock(&their_addr, &sock, NULL, port) == -1) { fprintf(stderr, "[error]: unable to get socket\n"); exit(1); } // Len of connecting address socklen_t addrlen = (socklen_t) sizeof(their_addr); // Last packet received int packet_received = -1; // Buffer to store data in char *buf = malloc((strlen(g_buffer) + 1) * sizeof(char)); char *bufstart = buf; // Main loop of execution - runs until we get an error or tear-down msg while (true) { // Receive a packet struct packet_t pkt; if (recv_packet(&pkt, sock, &their_addr, &addrlen, loss_rate) == -1) { fprintf(stderr, "[receiver]: couldn't receive packet\n"); exit(1); } // Check if this is the tear-down message. If so, get out of loop. if (pkt.type == 4) { printf("RECEIVED TEAR-DOWN PACKET\n"); break; } // Check if this is the next packet in the sequence. If so, adjust // packet_received appropriately and copy data to the buffer else if (pkt.seq_no == (packet_received + 1)) { packet_received++; strcpy(bufstart, pkt.data); bufstart += pkt.len; } printf("RECEIVED PACKET %d\n", pkt.seq_no); // Send ACK struct ack_t ack; if (make_ack(&ack, 2, packet_received) == -1) { fprintf(stderr, "[receiver]: couldn't construct ACK\n"); exit(1); } if (send_ack(&ack, sock, &their_addr) == -1) { fprintf(stderr, "[receiver]: couldn't send ACK %d\n", ack.ack_no); exit(1); } printf("--------SEND ACK %d\n", ack.ack_no + 1); printf("\n"); } // Construct ACK to tear-down message and send struct ack_t tear_down_ack; if (make_ack(&tear_down_ack, 8, 0) == -1) { fprintf(stderr, "[receiver]: couldn't construct tear-down ACK\n"); exit(1); } if (send_ack(&tear_down_ack, sock, &their_addr) == -1) { fprintf(stderr, "[receiver]: couldn't send tear-down ACK\n"); exit(1); } printf("--------SEND TEAR-DOWN ACK\n"); // Timer for 7 seconds. Additionally, set a timeout on the socket so that // we don't exceed the timeout by not receiving any packets if (set_timeout(sock, 7) == -1) { fprintf(stderr, "[receiver]: unable to set timeout\n"); exit(1); } clock_t start = clock(); int msec = (clock() - start) * 1000 / CLOCKS_PER_SEC; while (msec < 7000) { struct packet_t pkt; if (recv_packet(&pkt, sock, &their_addr, &addrlen, loss_rate) == -1) { break; } print_packet(pkt); if (pkt.type == 4) { printf("RECEIVED TEAR-DOWN PACKET\n"); } else { printf("RECEIVED PACKET %d\n", pkt.seq_no); } // Only ACK if it's a tear-down packet if (pkt.type == 4) { if (send_ack(&tear_down_ack, sock, &their_addr) == -1) { fprintf(stderr, "[receiver]: couldn't send tear-down ACK\n"); break; } printf("--------SEND TEAR-DOWN ACK\n"); } } free(buf); return 0; }