/** Author: Xiaoman Xu * Server side data link layer * receives frames and * reassembles it into a packet * and forward to to server netword layer **/ int datalink_recv(unsigned short sock, packet_t* packet, FILE* &outlog) { int frame_num = 0; size_t recv_at = 0; int recv_size = 0; frame_t frame, ack_frame;; bool valid, repeat = false; size_t packet_size = sizeof(packet_t); //while still more to receive while(recv_at < packet_size) { uint16_t frame_expected; frame_expected = ack_frame_send_seq; valid = false; //if the data frame received is not valid, //keep receiving while (!valid) { if((recv_size = physical_recv(sock, & frame)) != sizeof(frame_t)) { DieWithError("Server DataLink: Physical layer receive different size %d than expected", recv_size); } //if the data frame seq num is the frame expected, //then copy the data from the payload if(frame.sequence_num == frame_expected) { repeat = false; memcpy(((char*)packet) + recv_at, frame.payload, frame.length); } //selse the data frame is repeated. else { repeat = true; } // check whether the data frame is valid valid = frame.check == get_hash(&frame); if(!valid) fprintf(outlog, "Server data link layer: data frame %d of packet %d received in error (frame %d)\n", frame_num, packet_sent, frame_expected); } //open the log file if not already if(outlog == NULL) { char logname [20]; sprintf(logname, "server_%c.log", packet->filename[0]); outlog = fopen(logname, "w"); } ack_frame.type = FRAME_ACK; ack_frame.length = 0; ack_frame.sequence_num = ack_frame_send_seq; ack_frame.check = get_hash(&ack_frame); //send the ACK frame to client if(!repeat) { frame_num ++; fprintf(outlog, "Server Data Link: data frame %d of packet %d received.(frame %d)\n", frame_num, packet_sent, frame_expected); recv_at += frame.length; flip_frame(&ack_frame); ack_frame_send_seq++; } else { fprintf(outlog, "Server data link: data frame %d of packet %d repeated!(frame %d)\n", frame_num, packet_sent, frame_expected); } datalink_send_ACK(sock, &ack_frame); fprintf(outlog, "Server data link layer: ACK frame %d of packet %d sent.(frame %d)\n", frame_num, packet_sent, frame_expected); if(frame.is_end&&repeat) { return 0; } } packet_sent++; return sizeof(packet_t); }
//Author: Xiaoman Xu int datalink_send(unsigned short sock, packet_t *packet, FILE* outfile) { frame_t frame, ack_frame; uint8_t len = (uint8_t)FRAME_SIZE; unsigned int readpos = 0; int transmit_time = 0; size_t packet_size = sizeof(packet_t); //While still more to send in a packet, split the packet into //frames to transmit along physcial layer while(transmit_time < (int)packet_size/FRAME_SIZE + 1) { uint16_t frame_expected; frame_expected = frame_send_seq; frame.type = FRAME_DATA; frame.is_end = (transmit_time == (packet_size/FRAME_SIZE)); //Want to make sure get the right length if(frame.is_end) { len = packet_size % FRAME_SIZE; } memcpy(frame.payload, ((char*) packet) + readpos, len); frame.length = len; frame.sequence_num = frame_expected; //checksum frame.check = get_hash(&frame); //set a timer fd_set rfds; struct timeval tv; int retval; FD_ZERO(&rfds); FD_SET(sock,&rfds); tv.tv_sec=0; tv.tv_usec=50000; if(frame_expected == frame_sent) { //if the frame_expected is the frame already sent, record the same frame retransmitted fprintf(outfile, "Client Data Link: frame %d of packet %d retransmited.\t(frame %d)\n", transmit_time + 1, packet_sent, frame_expected); num_of_retransmission++; } else { //do error simulation flip_frame(&frame); fprintf(outfile, "Client Data Link: frame %d of packet %d sent.\t(frame %d)\n", transmit_time + 1, packet_sent, frame_expected); } //send along physcial layer; physical_send(sock, &frame); num_of_frame_sent ++; frame_sent = frame_send_seq; bool valid = false; //while not valid, keep receiving while (!valid) { int frame_ack = 1; //start the timer; retval = select(sock+1, &rfds,0, 0, &tv); if(retval == 0) { fprintf(outfile, "Client Data Link: time out after frame %d of packet %d sent.\t(frame %d)\n", transmit_time + 1, packet_sent, frame_expected); break; } else if(retval < 0) { DieWithError("Fail to set timer"); } else{ FD_ISSET(0, &rfds); } frame_ack = datalink_recvACK(sock, &ack_frame); fprintf(outfile, "Client Data Link: ACK frame %d of packet %d received.\t(ACK frame %d)\n", transmit_time + 1, packet_sent, ack_frame.sequence_num); //check whether the frame received is valid. valid = ack_frame.check == get_hash(&ack_frame); if(!valid) { fprintf(outfile, "Client Data Link: ACK frame %d of packet %d received in error.(ACK frame %d)\n", transmit_time + 1, packet_sent, ack_frame.sequence_num); num_of_errorACK ++; } else { num_of_goodACK ++; } if(!frame_ack) valid = false; //log_debug("ack_frame %d is valid? %d", frame.sequence_num, valid); } //if the frame acked succesfully, ready to send the next one if(valid) { readpos += len; frame_send_seq++; transmit_time++; } if(packet->last_photo && packet ->is_end && frame.is_end) { fprintf(outfile, "\nTotal frame sent: %d\nTotal retransmission: %d\nTotal goodACK: %d\nTotal badACK: %d\n\n", num_of_frame_sent, num_of_retransmission, num_of_goodACK, num_of_errorACK); } } //record the packet sent number packet_sent++; return packet_size; }
/*********************************************************************** * plugin main ppu thread ***********************************************************************/ static void vsh_menu_thread(uint64_t arg) { #ifdef DEBUG dbg_init(); dbg_printf("programstart:\n"); #endif uint16_t oldpad = 0, curpad = 0; CellPadData pdata; // wait for XMB, feedback sys_timer_sleep(13); //vshtask_notify("sprx running..."); play_rco_sound("system_plugin", "snd_trophy"); #ifdef HAVE_STARFIELD init_once(/* stars */); #endif // custom bg_color init a = GET_A(bg_color_menu[1]); r = GET_R(bg_color_menu[1]); g = GET_G(bg_color_menu[1]); b = GET_B(bg_color_menu[1]); while(1) { // if VSH Menu is running, we get pad data over our MyPadGetData() // else, we use the vsh pad_data struct if(menu_running) MyPadGetData(0, &pdata); else VSHPadGetData(&pdata); // if pad_data and we are in XMB(vshmain_EB757101() == 0) if((pdata.len > 0) && (vshmain_EB757101() == 0) ) { curpad = (pdata.button[2] | (pdata.button[3] << 8)); if((curpad & PAD_SELECT) && (curpad != oldpad)) { switch(menu_running) { // VSH Menu not running, start VSH Menu case 0: // main view and start on first entry view = line = 0; // pause_RSX_rendering(); // create VSH Menu heap memory from memory container 1("app") create_heap(64); // 64 MB // initialize VSH Menu graphic (init drawing context, alloc buffers, blah, blah, blah...) init_graphic(); // stop vsh pad start_stop_vsh_pad(0); // set menu_running menu_running = 1; break; // VSH Menu is running, stop VSH Menu case 1: stop_VSH_Menu(); // restart vsh pad start_stop_vsh_pad(1); break; } oldpad = 0; sys_timer_usleep(300000); } // VSH Menu is running, draw menu / check pad if(menu_running) { #ifdef DEBUG dbg_printf("%p\n", pdata); #endif draw_frame(&pdata); flip_frame(); if(curpad != oldpad) { if(curpad & PAD_UP) { if(line <= 0){ line = 0; }else{ line--; play_rco_sound("system_plugin", "snd_cursor"); } } if(curpad & PAD_DOWN) { if(line >= max_menu[view]-1){ line = max_menu[view]-1; }else{ line++; play_rco_sound("system_plugin", "snd_cursor"); } } if(curpad & PAD_LEFT || curpad & PAD_RIGHT) do_leftright_action(curpad); if(curpad & PAD_CROSS) do_menu_action(); } // ... sys_timer_usleep(30); } // end VSH Menu is running oldpad = curpad; }else{ oldpad = 0; } } #ifdef DEBUG dbg_fini(); #endif sys_ppu_thread_exit(0); }