void sendGetSW(int sock, struct sockaddr_in from) { packet *p; // check if the target chunkHash has been transferred by other peers // allow concurrent download while (queue_contains(peers[nodeInMap]->chunkHash) == EXIT_FAILURE) { if (peers[nodeInMap]->next == NULL ) { if (queue_empty() == EXIT_SUCCESS) { dprintf(STDOUT_FILENO, "JOB is done\n"); numDataMisses[nodeInMap] = -1; } return; } linkNode *temp = peers[nodeInMap]; peers[nodeInMap] = peers[nodeInMap]->next; free(temp); } if (peers[nodeInMap]->chunkHash == NULL ) { dprintf(STDOUT_FILENO, "sending chunk equals zero\n"); return; } p = packet_factory(GET); p->packet_length = 20 + BT_CHUNKS_SIZE; p->ack_num = 0; p->payload[0] = 1; p->payload[1] = '\0'; p->payload[2] = '\0'; p->payload[3] = '\0'; strncpy(p->payload + 4, peers[nodeInMap]->chunkHash, BT_CHUNKS_SIZE); spiffy_sendto(sock, p, p->packet_length, 0, (struct sockaddr *) &from, sizeof(from)); jobs[nodeInMap] = getChunkId(peers[nodeInMap]->chunkHash, chunkf); dprintf(STDOUT_FILENO, "Requesting chunk ID: %d from %d\n", jobs[nodeInMap], nodeInMap); nextExpected[nodeInMap] = 1; GETTTL[nodeInMap] = 0; free(p); // chunk is transferring, remove it from work queue so that // other peers won't transfer this again queue_remove(getChunkHash(jobs[nodeInMap], chunkf)); }
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; } }
std::ifstream* WavLoader::loadWav(String filename, int& format, int& rate, int& outSize) { std::ifstream* file = new std::ifstream(filename.c_str(), std::ios::in | std::ios::binary); if(!file->is_open()) throw Oryx::Exception("Could not open file."); // process the header char headerId[4]; char riffType[4]; uint32_t size; getChunkId(file, headerId); size = getChunkUInt32(file); getChunkId(file, riffType); // invalid wav if(String(headerId, 4) != "RIFF" || String(riffType, 4) != "WAVE") throw Oryx::Exception("Invalid WAV file."); // keep track of how many bytes have been processed uint32_t processed = 8; // data byte* data = 0; uint32_t dataSize = 0; // format info WavCompressionType compression; uint16_t numChannels; uint32_t sampleRate; uint32_t bytesPerSec; uint16_t blockAlign; uint16_t significantBitsPerSample; // process chunks while(file->good() && processed < size) { char chunkId[4]; uint32_t chunkSize; // assume we're starting on a chunk, this could go very wrong if we don't // do the chunk offsets correctly... getChunkId(file, chunkId); processed += 4; chunkSize = getChunkUInt32(file); processed += 4; if(String(chunkId,3) == "fmt") { compression = static_cast<WavCompressionType>(getChunkUInt16(file)); processed += 2; numChannels = getChunkUInt16(file); processed += 2; sampleRate = getChunkUInt32(file); processed += 4; bytesPerSec = getChunkUInt32(file); processed += 4; blockAlign = getChunkUInt16(file); processed += 2; significantBitsPerSample = getChunkUInt16(file); processed += 2; // skip any extra formating bytes file->ignore(chunkSize - 16); } else if(String(chunkId,4) == "data") { data = new byte[chunkSize]; dataSize = chunkSize; processed += chunkSize; // break right at the start of the data... break; } else // some other chunk type, ignore for now { file->ignore(chunkSize); processed += chunkSize; } // skip padding byte if chunk data isn't 2 byte aligned if(chunkSize & 1) { file->ignore(1); processed += 1; } } // determine format (this won't handle stuff with >2 channels..) format = numChannels == 1 ? blockAlign == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8: blockAlign == 4 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8; rate = sampleRate; outSize = dataSize; return file; }