Exemplo n.º 1
0
Arquivo: peer.c Projeto: SunnyQ/cmu
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));
}
Exemplo n.º 2
0
Arquivo: peer.c Projeto: SunnyQ/cmu
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;
    }
}
Exemplo n.º 3
0
	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;
	}