void process_inbound_udp(int sock) { #define BUFLEN 1500 struct sockaddr_in from; socklen_t fromlen; char buf[BUFLEN]; fromlen = sizeof(from); spiffy_recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); Packet *newPkt = newPacketFromBuffer(buf); memcpy(&(newPkt->src), &from, fromlen); handlePacket(newPkt); }
void process_inbound_udp(int sock) { #define BUFLEN 1500 struct sockaddr_in from; socklen_t fromlen; char buf[BUFLEN]; fromlen = sizeof(from); spiffy_recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); //parsing recvBuf unsigned short magic_number = ntohs(*(unsigned short*)buf); unsigned char packet_version = *(unsigned char*)(buf+2); unsigned char packet_type = *(unsigned char*)(buf+3); unsigned short packet_header_len = ntohs(*(unsigned short*)(buf+4)); unsigned short packet_len = ntohs(*(unsigned short*)(buf+6)); unsigned int seq_number =ntohl(*(unsigned int*)(buf+8)); unsigned int ack_number = ntohl(*(unsigned int*)(buf+12)); printf("%d,%d,%d\n", magic_number, packet_version, packet_type); printf("%d,%d\n", packet_header_len, packet_len); printf("PROCESS_INBOUND_UDP SKELETON -- replace!\n" "Incoming message from %s:%d\n%s\n\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf); switch(packet_type) { case WHOHAS: printf("receive WHOHAS\n"); break; case IHAVE: printf("receive IHAVE\n"); break; case GET: printf("receive GET\n"); break; case DATA: printf("receive DATA\n"); break; case ACK: printf("receive ACK\n"); break; case DENIED: printf("receive DENIED\n"); break; default: printf("Unexpected packet type!\n"); } }
void process_inbound_udp(int sock) { static char buf[BT_MAX_PKT_SIZE]; struct sockaddr_in from; socklen_t fromlen = sizeof(from); int ret = spiffy_recvfrom(sock, buf, BT_MAX_PKT_SIZE, 0, (struct sockaddr *) &from, &fromlen); buf[ret] = 0; data_packet_t packet = * (data_packet_t *) buf; packet.data = buf + sizeof(header_t); if(packet.header.magicnum != BT_MAGIC){ printf("Ignoring unrecognizable packet\n"); return; } bt_peer_t *p; for (p = config.peers; p != NULL; p = p->next) { if (!memcmp(&p->addr.sin_addr, &from.sin_addr, sizeof(struct in_addr)) && p->addr.sin_port == from.sin_port) { break; } } if(p == NULL){ printf("Ignoring packet from unknown peer\n"); return; } int peer = p->id; if(packet.header.packet_type == 1 || packet.header.packet_type == 3 || packet.header.packet_type == 5){ requestor_packet(&requestor, peer, &packet); }else if(packet.header.packet_type == 0 || packet.header.packet_type == 2){ responser_packet(&responser, peer, &packet); }else{ int i; for(i=0; i<BT_MAX_UPLOAD; ++i){ if(!senders[i].is_idle && senders[i].peer == peer){ ctl_udp_ack(&senders[i], peer, &packet); } } } }
void process_inbound_udp(int sock, bt_config_t *config) { struct sockaddr_in from; socklen_t fromlen; char **chunk_list; char **haschunk_list; packet incomingPacket; bt_peer_t *curPeer; packet *p; int i; rttRecord *tempRtt; fromlen = sizeof(from); spiffy_recvfrom(sock, &incomingPacket, sizeof(incomingPacket), 0, (struct sockaddr *) &from, &fromlen); // check the node where the packet comes from depending on ip and port for (curPeer = config->peers; curPeer != NULL ; curPeer = curPeer->next) if (strcmp(inet_ntoa(curPeer->addr.sin_addr), inet_ntoa(from.sin_addr)) == 0 && ntohs(curPeer->addr.sin_port) == ntohs(from.sin_port)) nodeInMap = curPeer->id; switch (incomingPacket.type) { case WHOHAS: // sender dprintf(STDOUT_FILENO, "WHOHAS received\n"); chunk_list = retrieve_chunk_list(&incomingPacket); haschunk_list = has_chunks(config, &incomingPacket, chunk_list); if (haschunk_list[0] != NULL ) sendback_response(sock, haschunk_list, incomingPacket.payload[0], from); free_chunks(chunk_list, incomingPacket.payload[0]); free_chunks(haschunk_list, incomingPacket.payload[0]); break; case IHAVE: // requester dprintf(STDOUT_FILENO, "IHAVE received\n"); chunk_list = retrieve_chunk_list(&incomingPacket); allocate_peer_chunks(chunk_list, incomingPacket.payload[0]); sendGetSW(sock, from); free_chunks(chunk_list, incomingPacket.payload[0]); break; case GET: // sender dprintf(STDOUT_FILENO, "GET received\n"); chunk_list = retrieve_chunk_list(&incomingPacket); jobs[nodeInMap] = getChunkId(chunk_list[0], config->has_chunk_file); // send a window to requester //congestion control started windowSize[nodeInMap] = 1; congestionState[nodeInMap] = 0; ssthresh[nodeInMap] = 64; lastSent[nodeInMap] = 0; for (i = 0; i < windowSize[nodeInMap]; i++) sendData(from, config); recordWindowSize(config); free_chunks(chunk_list, incomingPacket.payload[0]); break; case DATA: // requester dprintf(STDOUT_FILENO, "DATA received %d from %d\n", incomingPacket.sequence_num, nodeInMap); GETTTL[nodeInMap] = -1; // if sequence_num < expected, ignore as they might be channel-queued packets // if sequence_num > expected, something is lost or in wrong order if (incomingPacket.sequence_num > nextExpected[nodeInMap] && numMismatches < 3) { p = packet_factory(ACK); p->packet_length = 16; p->ack_num = nextExpected[nodeInMap] - 1; spiffy_sendto(sock, p, p->packet_length, 0, (struct sockaddr *) &from, sizeof(from)); numMismatches++; numDataMisses[nodeInMap] = 0; } else if (incomingPacket.sequence_num == nextExpected[nodeInMap]) { numDataMisses[nodeInMap] = 0; numMismatches = 0; processData(&incomingPacket, config, sock, from); nextExpected[nodeInMap] = incomingPacket.sequence_num + 1; if (incomingPacket.sequence_num == BT_CHUNK_SIZE && peers[nodeInMap]->next != NULL ) { dprintf(STDOUT_FILENO, "Got %s\n", peers[nodeInMap]->chunkHash); linkNode *temp = peers[nodeInMap]; //cp1 peers[nodeInMap] = peers[nodeInMap]->next; free(temp); sendGetSW(sock, from); } else if (incomingPacket.sequence_num == BT_CHUNK_SIZE && peers[nodeInMap]->next == NULL ) { dprintf(STDOUT_FILENO, "JOB is done\n"); numDataMisses[nodeInMap] = -1; } } break; case ACK: dprintf(STDOUT_FILENO, "ACK received %d\n", incomingPacket.ack_num); // sender if (lastACKed[nodeInMap] == incomingPacket.ack_num) dup_ack[nodeInMap]++; // similarly, smaller received ack can be channel queued, ignore else if (incomingPacket.ack_num != lastACKed[nodeInMap] + 1) return; // duplicate acked else dup_ack[nodeInMap] = 0; // clear DATA TTL TTL[nodeInMap][incomingPacket.ack_num - 1] = -1; // retransmit if (dup_ack[nodeInMap] == 3) //loss { dprintf(STDOUT_FILENO, "dup retransmitting\n"); congestionControlRetransmit(config); //change windowSize lastSent[nodeInMap] = lastACKed[nodeInMap]; sendData(from, config); dup_ack[nodeInMap] = 0; } else //normal { congestionControlNormal(&incomingPacket, config); lastACKed[nodeInMap] = incomingPacket.ack_num; // ok... task finished if (incomingPacket.ack_num == BT_CHUNK_SIZE) { jobs[nodeInMap] = -1; lastACKed[nodeInMap] = 0; lastSent[nodeInMap] = 0; windowSize[nodeInMap] = 0; congestionState[nodeInMap] = -1; ssthresh[nodeInMap] = 64; resetCCRTT(); dprintf(STDOUT_FILENO, "JOB is done\n"); numDataMisses[nodeInMap] = -1; } else { for (i = lastSent[nodeInMap]; i < lastACKed[nodeInMap] + windowSize[nodeInMap] && i < BT_CHUNK_SIZE; i++) sendData(from, config); if (congestionState[nodeInMap] == CA) //test the RTT timer { if (headRTT != NULL ) { for (tempRtt = headRTT; tempRtt->next != NULL ; tempRtt = tempRtt->next) ; tempRtt->next = (rttRecord *) malloc(sizeof(rttRecord)); tempRtt->next->seq = lastSent[nodeInMap]; tempRtt->next->next = NULL; } else { headRTT = (rttRecord *) malloc(sizeof(rttRecord)); headRTT->seq = lastSent[nodeInMap]; headRTT->next = NULL; } } } } break; case DENIED: dprintf(STDOUT_FILENO, "DENIED received\n"); break; default: perror("Unknown Command: Ignored...\n"); break; } }
void process_inbound_udp(int sock) { #define BUFLEN 1500 struct sockaddr_in from; socklen_t fromlen; char buf[BUFLEN]; fromlen = sizeof(from); spiffy_recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); //recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); packetHead* pHead = (packetHead* )buf; peerEle* peer = resolvePeer(from, peerList); switch(pHead->type){ case WHOHAS:{ printf("Recieve WHOHAS request\n"); void* ihavep = ihaveCons(buf, &haschunkList); if( ihavep!= NULL){ unsigned int bufSize = ((packetHead *)ihavep)->packLen; spiffy_sendto(sock, ihavep, bufSize, 0, (struct sockaddr *) &from, fromlen); //sendto(sock, ihavep, bufSize, 0, (struct sockaddr *) &from, fromlen); time(&start); } break; } case IHAVE:{ printf("Receieve IHAVE request\n"); printf("packet length is %u\n", pHead->packLen); char tmp[sizeofHash]; memcpy(tmp, (buf+20), sizeofHash); printf("chunk hash: %s\n", tmp); peerEle* thisPeer = resolvePeer(from, peerList); time_t finish; time(&finish); if( thisPeer == NULL ){ printf("RESOLVE FAILED\n"); } thisPeer->rtt = difftime(finish, start); AddResponses(thisPeer, buf, &chunkList, sock); printChunkList(chunkList); break; } case GET:{ printf("Receive GET Request\n"); printf("packet length is %u\n", pHead->packLen); //check for free connections printf("maxcon:%d id: %d numout: %d\n",maxCon,mePeer->id,mePeer->numOut); if(mePeer->numOut == maxCon){ chunkEle* dcp = lookupChunkHash((buf+20),&haschunkList); void* deniedp = deniedCons(dcp->chunkId); spiffy_sendto(sock, deniedp, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); //sendto(sock, deniedp, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); break; } chunkEle* thisWindow = buildNewWindow(&windowSets, &haschunkList, peer, masterDataFilePath, buf); // send first element, no need to clean or fill sendWindow(thisWindow, sock); mePeer->numOut++;//increase num break; } case DATA:{ unsigned int bufSize = ((packetHead *)buf)->packLen; void* newBuf = malloc(bufSize); memcpy(newBuf,buf,bufSize); chunkEle* cep = resolveChunk(peer, chunkList); getRetryTimer = 0; // reject packets from finished chunk if(cep && (cep->chunkId != ((packetHead*)buf)->ackNum)){ printf("Wrong chunk!\n"); break; } orderedAdd(cep,newBuf); printf("Receive data packet %d, with size %d \n", ((packetHead *)buf)->seqNum, ((packetHead *)buf)->packLen - headerSize); findMex(cep); printPacketList(cep->packetList); void* packet = ackCons(cep->nextExpectedSeq - 1); printf("Send Ack %d\n", cep->nextExpectedSeq - 1); spiffy_sendto(sock, packet, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); //sendto(sock, packet, headerSize, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); printf("bytes read for hash %s : %d\n",cep->chunkHash, cep->bytesRead); //check if finish receiving the whole chunk if(cep->bytesRead == chunkSize ){ if ( cep->fromThisPeer->inUse == 1){ printf("Sucessfully receive the chunk %s\n", cep->chunkHash); chunkList.finished ++; cep->fromThisPeer->inUse = 0; cep->inProgress = 0; mePeer->numOut--; } printf("FINISHED %d\n", chunkList.finished); if(chunkList.finished == chunkList.length){ printf("Finish receiving the whole file\n"); // merge the chunks and write to the corresponding output file buildOuputFile(outputFile, &chunkList); fclose(outputFile); printf("GOT %s\n",outputFilePath); }else{ // try to send rest of pending get requests // they are deferred to make sure no concurrent downloading from the same peer sendPendingGetRequest(&chunkList, sock); } } break; } case ACK:{ chunkEle* cep = resolveChunk(peer, windowSets); if ( cep->inProgress == 0){ break; } //check which wether SLOWSTART or CONGAVOID if(cep->mode == SLOWSTART){ cep->windowSize++; printf("####in slow start\n"); } else printf("@@@@in cong avoid rtt: %f\n",cep->fromThisPeer->rtt); //check if enough to enter cong avoid if(cep->windowSize == cep->ssthresh) cep->mode = CONGAVOID; //check for no ack in rtt if((cep->mode == CONGAVOID) && (cep->haveACK == 0)){ cep->windowSize++; printf("IIIIincreasing in cong avoid\n"); } //set ack cep->haveACK = 1; printf("Receive Ack %d\n", *(int*)(buf+12)); if( (cep->lastAcked) && ((packetHead* )(cep->lastAcked->data))->seqNum == ((packetHead* )(buf))->ackNum ){ cep->lastAckedCount ++; printf("Incrementing last ack counter for %d to %d\n", ((packetHead* )(buf))->ackNum,cep->lastAckedCount); if( cep->lastAckedCount == 3 ){ //cut ssthresh in half and set window 1 cep->ssthresh = halve(cep->windowSize); cep->windowSize = 1; cep->mode = SLOWSTART; //reset this ones time time(&cep->afterLastAckedTime); //try retrasmit cep->lastAckedCount = 0; node* retry = cep->lastAcked->prevp; printf("Retramsmit packet %d\n", ((packetHead* )retry->data)->seqNum); spiffy_sendto(sock, retry->data, ((packetHead* )retry->data)->packLen, 0, (struct sockaddr *) &peer->cli_addr, sizeof(peer->cli_addr)); break; } }else{ cep->lastAcked = resolveLastPacketAcked( ((packetHead*)buf)->ackNum, cep); cleanList(cep); time(&cep->afterLastAckedTime); } //check if finish sending the whole chunk if( cep->bytesRead == chunkSize ){ printf("Successfully send the chunk %s\n", cep->chunkHash); if(cep->lastAcked == cep->lastSent){ // some clear below printf("All sent packets have been acked\n"); cep->inProgress = 0; mePeer->numOut--; }else{ printf("lastAcked:%d, lastSent:%d\n",((packetHead*)cep->lastAcked->data)->seqNum, ((packetHead*)cep->lastSent->data)->seqNum ); } }else{ cleanList(cep); fillWindow(cep); sendWindow(cep, sock); } printPacketList(cep->packetList); printf("window: %d, ssthresh: %d, mode: %d\n",cep->windowSize, cep->ssthresh, cep->mode); break; } case DENIED:{ printf("Received a denied ack!\n"); chunkEle* cep = resolveChunk(peer, chunkList); //fclose(outputFile); time(&getRetryTimer); cep->fromThisPeer->inUse = 0; break; } } printf("PROCESS_INBOUND_UDP SKELETON -- replace!\n" "Incoming message from %s:%d\n%s\n\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf); }
void process_inbound_udp(int sock) { struct sockaddr_in from; socklen_t fromlen; char buf[MAX_PACKET_LENGTH]; fromlen = sizeof(from); int read_result = spiffy_recvfrom(sock, buf, MAX_PACKET_LENGTH, 0, (struct sockaddr *) &from, &fromlen); printf("read %d bytes\n", read_result); //printf("incoming message from %s:%d\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); /* we just assume we got one packet everytime * if there are multiple packets in the buffer (whichi is rare), we just ignore them, * and everything will just work fine. */ struct network_packet_s* network_packet = (struct network_packet_s*)buf; net_to_host_header(& network_packet->header); print_packet_header(&network_packet->header); if(validate_packet(& network_packet->header) < 0){ printf("packet is invalid, skip\n"); return; } int packet_type = get_packet_type(& network_packet->header); /* get the peer who send this packet*/ bt_peer_t* peer = search_bt_peer(&config, (struct sockaddr *)&from); switch(packet_type) { case TYPE_WHOHAS: { struct network_packet_s* ihave_packet = malloc_ihave_packet(network_packet); /* this node has no such chunk */ if(ihave_packet == NULL){ return; } else{ //print_ihave_packet(ihave_packet); send_packet(ihave_packet, global_socket, (struct sockaddr *) &from); free(ihave_packet); } break; } case TYPE_IHAVE: { if(current_job == NULL){ return; } /* receiving a new IHAVE packet */ /* check whether there is alreay a connection with this peer */ struct receiver_connection_s* existing_connection = search_receiver_connection(receiver_connection_head, peer); if(existing_connection != NULL){ /* there is alreay a connection */ add_ihave_to_receiver_connection(existing_connection, network_packet); } /* there is no such connection */ else{ /* check if the number of connection reached the maximum */ if(get_receiver_connection_number(receiver_connection_head) >= max_receiver_connection){ return; } /* add add the hash whose chunk is in a CHUNK_STATUS_NOT_FOUND status * to a new connection */ else{ struct receiver_connection_s* new_connection = malloc_receiver_connection(network_packet, peer); /* if every chunk has a provider, the new_connection is NULL */ if(new_connection != NULL){ add_receiver_connection(new_connection); /* start the new connection */ struct network_packet_s* get_packet = start_connection(new_connection); //print_get_packet(get_packet); free(get_packet); } } } //print_receiver_connection_list(receiver_connection_head); break; } case TYPE_GET: { //print_get_packet(network_packet); /* check whether there is alreay a connection with this peer */ if(search_provider_connection(provider_connection_head, peer) != NULL){ printf("Provider connection already exists with peer %d , ignore GET\n", peer->id); return; } /* do nothing is the number of connection reached the maximum*/ if(get_provider_connection_number(provider_connection_head) >= max_provider_connection){ printf("Provider connection reached maximum with peer %d \n", peer->id); return; } struct provider_connection_s* new_connection = malloc_provider_connection(network_packet, peer); if(new_connection != NULL){ printf("Add new provider connection with peer %d \n", peer->id); add_provider_connection(new_connection); //print_provider_connection(new_connection); } //print_provider_connection_list(provider_connection_head); break; } case TYPE_DATA: { print_data_packet(network_packet); printf("received data packet, seq: %d, ack: %d\n ", network_packet->header.seq_number, network_packet->header.ack_number); /* check whether there is a connection with this peer */ struct receiver_connection_s* receiver_connection = search_receiver_connection(receiver_connection_head, peer); /* connection does not exist, ignore the data packet */ if(receiver_connection == NULL){ return; } int existing_seq_num = receiver_connection->chunk_list_head->chunk->received_seq_num; printf("expected data packet, seq: %d \n", 1 + existing_seq_num); int packet_seq_num = network_packet->header.seq_number; /* sequence number is illegal */ if(packet_seq_num < 0){ return; } /* old packet arrived, do nothing */ else if(packet_seq_num < (existing_seq_num + 1)){ return; } /* latter packet arrived first, send duplicate ACK */ else if(packet_seq_num > (existing_seq_num + 1)){ struct network_packet_s* ack_packet = malloc_ack_packet(existing_seq_num); send_packet(ack_packet, global_socket, (struct sockaddr *) &from); free(ack_packet); return; } /* the packet expected */ else{ gettimeofday(&receiver_connection->last_data_time, NULL); receiver_connection->status = RECEIVER_STATUS_RECEIVED_DATA; struct network_packet_s* ack_packet = malloc_ack_packet(1 + existing_seq_num); send_packet(ack_packet, global_socket, (struct sockaddr *) &from); free(ack_packet); /* save_data_packet */ save_data_packet(network_packet, receiver_connection); /* save the downloading chunk of the connnection, if it finihsed */ save_chunk(receiver_connection); /* continue to download next chunk, if finished first one */ reset_receiver_connection(receiver_connection); } break; } case TYPE_ACK: { //print_ack_packet(network_packet); struct provider_connection_s* provider_connection = search_provider_connection(provider_connection_head, peer); if(provider_connection == NULL){ return; } provider_control_by_ack(provider_connection, network_packet->header.ack_number); /* check if the data has been all send to a receiver */ if(provider_connection->last_packet_acked == CHUNK_DATA_NUM){ /* download finished */ finish_provider_connection(provider_connection); } break; } case TYPE_DENIED: { break; } default:{ break; } } }
void process_inbound_udp(int sock) { printf("\n"); // DEBUG #define BUFLEN 1500 struct sockaddr_in from; socklen_t fromlen; char buf[BUFLEN]; fromlen = sizeof(from); spiffy_recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *) &from, &fromlen); /* printf("PROCESS_INBOUND_UDP SKELETON -- replace!\n" "Incoming message from %s:%d\n%s\n\n", inet_ntoa(from.sin_addr), ntohs(from.sin_port), buf); */ /* first generate the incoming packet */ data_packet_t *recv_packet = build_packet_from_buf(buf); //recv_packet->header.ack_num = ntohl(recv_packet->header.ack_num); //recv_packet->header.seq_num = ntohl(recv_packet->header.seq_num); /* next parse this packet and build the response packet*/ bt_peer_t *node; short target_id = -1; node = config.peers; while(node!=NULL){ if( from.sin_family == node->addr.sin_family && from.sin_port == node->addr.sin_port && from.sin_addr.s_addr == node->addr.sin_addr.s_addr) { target_id = node->id; break; } node = node->next; } if( target_id == -1){ printf("Can not locate id %d, %d, %d\n",from.sin_family, from.sin_port, from.sin_addr.s_addr ); return; } data_packet_list_t *response_list = handle_packet(recv_packet, &config, (int)target_id, p_tracker); /* NEW: add parameter socket address from the one who send the packet */ //data_packet_list_t *response_list = handle_packet(packet, &config, sock, p_tracker); /* finally call spiffy_sendto() to send back the packet*/ if( NULL == response_list ){ /* can not generate a response or no data avaiable */ return; } else{ data_packet_list_t *head; response_list = reverseList(response_list); for( head = response_list; head != NULL; head = head->next ){ data_packet_t *packet = head->packet; if( packet->header.packet_type == 3 ){ printf("DEBUG : SEND DATA SEQ = %d\n", packet->header.seq_num); } if( packet->header.packet_type == 4 ){ printf("DEBUG : SEND ACK ACK = %d\n", packet->header.ack_num); } /* check timer if already send and within timeout , then dont send */ packet_tracker_t *head; int find = 0; for( head = p_tracker ; head != NULL ;head = head->next ){ if( head->packet->header.seq_num == packet->header.seq_num && head->packet->header.ack_num == packet->header.ack_num){ if( -1 == timer_expired(head) ){ find = 1; } } } if( find == 0){ if( packet->header.packet_type == 3){ p_tracker = create_timer(p_tracker, packet, (int)target_id, &from); } packet_tracker_t * p = p_tracker; while( p != NULL){ printf("(%d,%d) - ",p->seq, p->sock); p = p->next; } printf("\n"); int r = rand(); if( r % 20 < -5 &&( packet->header.packet_type == 3 || packet->header.packet_type == 4)){ /* use a random number to simulate the packet loss , currently it is 100% deliver */ printf("RANDOM DISCARD THIS PACKET\n"); continue; } else{ packet->header.ack_num = ntohl(packet->header.ack_num); packet->header.seq_num = ntohl(packet->header.seq_num); int ret = spiffy_sendto(sock, packet, ntohs(packet->header.packet_len), 0, (struct sockaddr *) &from, sizeof(struct sockaddr)); if( ret <= 0 ) printf("Inbound_udp send to sock %d ret = %d", sock, ret); } } else if( find == 1){ if( packet->header.packet_type != 3){ int ret = spiffy_sendto(sock, packet, ntohs(packet->header.packet_len), 0, (struct sockaddr *) &from, sizeof(struct sockaddr)); if( ret <= 0 ) printf("Inbound_udp send to sock %d ret = %d", sock, ret); } printf("Not timeout dont send this packet or not find"); } } } }