예제 #1
0
파일: protocol_dec.c 프로젝트: nja/dumhet
Message *Message_Decode(char *data, size_t len, struct PendingResponses *pending)
{
    assert(data != NULL && "NULL data pointer");

    BNode *dict = NULL;
    Message *message = calloc(1, sizeof(Message));
    check_mem(message);

    dict = BDecode(data, len);

    if (dict == NULL || dict->type != BDictionary)
    {
        BNode_Destroy(dict);
        message->type = MUnknown;
        message->errors |= MERROR_UNKNOWN_TYPE;
        return message;
    }

    char y = GetMessageType(dict);

    int rc = 0;

    switch(y)
    {
    case 'q':
        rc = DecodeQuery(message, dict);
        check(rc == 0, "DecodeQuery failed");
	break;
    case 'r':
        rc = DecodeResponse(message, dict, pending);
        check(rc == 0, "DecodeResponse failed");
	break;
    case 'e':
        rc = DecodeError(message, dict);
        check(rc == 0, "DecodeError failed");
	break;
    default:
        message->errors |= MERROR_UNKNOWN_TYPE;
	break;
    }

    BNode_Destroy(dict);

    return message;
error:
    BNode_Destroy(dict);
    return NULL;
}
예제 #2
0
void HandleClient(ConnectionPeer clientPeer, ConnectionPeer serverPeer, std::mutex &outputMutex)
{
    bool close = false;
    size_t messageLength = 0;

    while (!close) {
        while ((messageLength = MessageLength(clientPeer.peek())) == 0)
            std::this_thread::yield();

        std::chrono::system_clock::time_point before = std::chrono::system_clock::now();

        std::string message = clientPeer.read(messageLength);
        serverPeer.write(message);

        close = (DecodeQuery(message).size() == 0);

        outputMutex.lock();
        std::cout << "S_LB "
                  << std::chrono::duration_cast<std::chrono::microseconds>(
                          std::chrono::system_clock::now() - before).count()
                  << '\n';
        outputMutex.unlock();

        if (!close) {
            while ((messageLength = MessageLength(serverPeer.peek())) == 0)
                std::this_thread::yield();

            before = std::chrono::system_clock::now();

            message = serverPeer.read(messageLength);
            clientPeer.write(message);

            outputMutex.lock();
            std::cout << "S_LB "
                      << std::chrono::duration_cast<std::chrono::microseconds>(
                              std::chrono::system_clock::now() - before).count()
                      << '\n';
            outputMutex.unlock();
        }
    }

    clientPeer.close();
    serverPeer.close();
}
예제 #3
0
/** This version of DecodeMessageData() can NOT extract a 'v' region
since the original string has already been parsed outside the scope of this object. */
void DHTMessage::DecodeMessageData(BencodedDict &bDict)
{
	_bDictForUser = &bDict;

	// if not a dictionary, it's not a valid DHT RPC
	if(bDict.GetType() != BENC_DICT)
	{
		_parseSuccessful = false;
		dhtMessageType = DHT_UNDEFINED_MESSAGE;
		return;
	}
	_parseSuccessful = true;

	// extract the components common to all DHT messages
	transactionID.b = (byte*)bDict.GetString("t", &transactionID.len);
	version.b = (byte*)bDict.GetString("v", &version.len);
	external_ip.b = (byte*)bDict.GetString("ip", &external_ip.len);
	read_only = bDict.GetInt("ro", 0) != 0;

	type = bDict.GetString("y", 1);
	if (!type)
		return;

	switch(*type)
	{
		case 'q':
		{
			dhtMessageType = DHT_QUERY;
			DecodeQuery(bDict);
			break;
		}
		case 'r':
		{
			// Just extract the reply dictionary.  Specific elements can be
			// extracted further down the call chain once it is known what
			// specific query this is a reply to.
			replyDict = bDict.GetDict("r");
			if(replyDict){
				id = (byte*)replyDict->GetString("id", DHT_ID_SIZE);
				dhtMessageType = DHT_RESPONSE;
				sequenceNum = replyDict->GetInt("seq", 1);
				vBuf.len = region.second - region.first;
				vBuf.b = region.first;
				signature.b = (byte*)replyDict->GetString("sig", &signature.len);
				key.b = (byte*)replyDict->GetString("k", &key.len);
			}
			else {
				dhtMessageType = DHT_UNDEFINED_MESSAGE;
			}

			break;
		}
		case 'e':
		{
			dhtMessageType = DHT_ERROR;
			DecodeError(bDict);
			break;
		}
		default:
			dhtMessageType = DHT_UNDEFINED_MESSAGE;
	}
}