Beispiel #1
0
void
athena_EncodeMessage(CCNxMetaMessage *message)
{
    PARCSigner *signer = ccnxValidationCRC32C_CreateSigner();
    CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvPacket_DictionaryEncode(message, signer);
    assertTrue(ccnxWireFormatMessage_PutIoVec(message, iovec), "ccnxWireFormatMessage_PutIoVec failed");;
    ccnxCodecNetworkBufferIoVec_Release(&iovec);
    parcSigner_Release(&signer);
}
LONGBOW_TEST_CASE(Global, ccnxWireFormatMessage_FromInterestPacketTypeIoVec)
{
    uint8_t data[64];

    uint8_t pad[32];
    CCNxCodecNetworkBufferIoVec *vec = _createNetworkBufferIoVec(512, 32, pad, 64, data);

    CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromInterestPacketTypeIoVec(CCNxTlvDictionary_SchemaVersion_V1, vec);

    assertNotNull(message, "Got null CCNxWireFormatMessage");
    assertTrue(ccnxTlvDictionary_IsInterest(message), "Wrong message type");
    assertTrue(ccnxTlvDictionary_GetSchemaVersion(message) == CCNxTlvDictionary_SchemaVersion_V1,
               "Wrong schema, got %d expected %d",
               ccnxTlvDictionary_GetSchemaVersion(message), CCNxTlvDictionary_SchemaVersion_V1);

    ccnxWireFormatMessage_Release(&message);
    ccnxCodecNetworkBufferIoVec_Release(&vec);
}
LONGBOW_TEST_CASE(Global, ccnxWireFormatMessage_PutGetIoVec)
{
    uint8_t *data = parcMemory_Allocate(64);
    memset(data, 0, 64);

    PARCBuffer *buffer = parcBuffer_Allocate(1);
    CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_CreateFromArray(&ParcMemoryMemoryBlock, NULL, 64, data);
    CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff);

    CCNxTlvDictionary *packet = ccnxCodecSchemaV1TlvDictionary_CreateInterest();
    ccnxWireFormatMessage_PutIoVec((CCNxWireFormatMessage *) packet, iovec);

    CCNxCodecNetworkBufferIoVec *test = ccnxWireFormatMessage_GetIoVec((CCNxWireFormatMessage *) packet);
    assertTrue(test == iovec, "Failed to get iovec from dictionary, expected %p got %p", (void *) iovec, (void *) test);

    ccnxTlvDictionary_Release(&packet);
    parcBuffer_Release(&buffer);
    ccnxCodecNetworkBufferIoVec_Release(&iovec);
    ccnxCodecNetworkBuffer_Release(&netbuff);
}
LONGBOW_TEST_CASE(Global, ccnxWireFormatMessage_CreateContentObjectHash)
{
    //                         >1234<
    const char string[] = "Hello dev null\n";

    PARCBuffer *buffer = parcBuffer_Wrap((void *) string, sizeof(string), 0, sizeof(string));

    CCNxWireFormatMessage *message = ccnxWireFormatMessage_FromContentObjectPacketType(CCNxTlvDictionary_SchemaVersion_V1, buffer);

    PARCCryptoHash *hash = ccnxWireFormatMessage_CreateContentObjectHash(message);
    ccnxWireFormatMessage_Release(&message);
    assertNull(hash, "Expect NULL for hash as it hasn't been encoded yet");

    // We need to create a content object that is hashable
    CCNxName *name = ccnxName_CreateFromCString("lci:/test/content");
    CCNxContentObject *contentObject = ccnxContentObject_CreateWithNameAndPayload(name, buffer);
    ccnxName_Release(&name);

    // This next stuff is to force an encode/decode to setup hash extents
    CCNxCodecNetworkBufferIoVec *iovec = ccnxCodecTlvPacket_DictionaryEncode(contentObject, NULL);
    ccnxContentObject_Release(&contentObject);
    PARCBuffer *encodedMessage = _iovecToParcBuffer(iovec);
    ccnxCodecNetworkBufferIoVec_Release(&iovec);
    // Decode
    message = ccnxWireFormatMessage_Create(encodedMessage);
    CCNxTlvDictionary *dictionary = ccnxWireFormatMessage_GetDictionary(message);
    bool success = ccnxCodecTlvPacket_BufferDecode(encodedMessage, dictionary);
    assertTrue(success, "Failed to decode buffer");
    parcBuffer_Release(&encodedMessage);

    hash = ccnxWireFormatMessage_CreateContentObjectHash(message);

    // the correctness of the hash is tested in _ccnxWireFormatFacadeV1_ComputeHash
    assertNotNull(hash, "Got null hash from a good packet");

    ccnxWireFormatMessage_Release(&message);
    parcCryptoHash_Release(&hash);
    parcBuffer_Release(&buffer);
}
static int
_ETHSend(AthenaTransportLink *athenaTransportLink, CCNxMetaMessage *ccnxMetaMessage)
{
    struct _ETHLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink);

    if (ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage) == CCNxTlvDictionary_SchemaVersion_V0) {
        parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink),
                      "sending deprecated version %d message\n", ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage));
    }

    // Construct our header to prepend
    struct ether_header header;
    memcpy(header.ether_shost, &(linkData->link.myAddress), ETHER_ADDR_LEN * sizeof(uint8_t));
    memcpy(header.ether_dhost, &(linkData->link.peerAddress), ETHER_ADDR_LEN * sizeof(uint8_t));
    header.ether_type = htons(athenaEthernet_GetEtherType(linkData->athenaEthernet));

    // An iovec to contain the header and packet data
    struct iovec iov[2];
    struct iovec *array = iov;
    int iovcnt = 2;
    size_t messageLength = 0;

    // If the iovec we're prepending to has more than one element, allocatedIovec holds the
    // allocated IO vector of the right size that we must deallocate before returning.
    struct iovec *allocatedIovec = NULL;

    // Attach the header and populate the iovec

    CCNxCodecNetworkBufferIoVec *iovec = athenaTransportLinkModule_GetMessageIoVector(ccnxMetaMessage);

    iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec);
    const struct iovec *networkBufferIovec = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec);

    // Trivial case, single iovec element.
    if (iovcnt == 1) {
        // Header
        array[0].iov_len = sizeof(struct ether_header);
        array[0].iov_base = &header;

        // Message content
        array[1].iov_len = networkBufferIovec->iov_len;
        array[1].iov_base = networkBufferIovec->iov_base;
        messageLength = array[0].iov_len + array[1].iov_len;
    } else {
        // Allocate a new iovec if more than one vector
        allocatedIovec = parcMemory_Allocate(sizeof(struct iovec) * (iovcnt + 1));
        array = allocatedIovec;

        // Header
        array[0].iov_len = sizeof(struct ether_header);
        array[0].iov_base = &header;
        messageLength = array[0].iov_len;

        // Append message content
        for (int i = 0; i < iovcnt; i++) {
            array[i + 1].iov_len = networkBufferIovec[i].iov_len;
            array[i + 1].iov_base = networkBufferIovec[i].iov_base;
            messageLength += array[i + 1].iov_len;
        }
    }
    iovcnt++; // increment for the header

    if (linkData->link.mtu) {
        if (messageLength > linkData->link.mtu) {
            if (allocatedIovec != NULL) {
                parcMemory_Deallocate(&allocatedIovec);
            }
            ccnxCodecNetworkBufferIoVec_Release(&iovec);
            errno = EMSGSIZE;
            return -1;
        }
    }

    parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink),
                  "sending message (size=%d)", messageLength);

    ssize_t writeCount = 0;
    writeCount = athenaEthernet_Send(linkData->athenaEthernet, array, iovcnt);
    ccnxCodecNetworkBufferIoVec_Release(&iovec);

    // Free up any storage allocated for a non-singular iovec
    if (allocatedIovec != NULL) {
        parcMemory_Deallocate(&allocatedIovec);
        array = NULL;
    }

    // on error close the link, else return to retry a zero write
    if (writeCount == -1) {
        if ((errno == EAGAIN) || (errno == EINTR)) {
            parcLog_Info(athenaTransportLink_GetLogger(athenaTransportLink), "send retry");
            linkData->_stats.send_Retry++;
            return -1;
        }
        athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Error);

        parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink),
                      "send error (%s)", strerror(errno));
        linkData->_stats.send_Error++;
        return -1;
    }

    // Short write
    if (writeCount != messageLength) {
        linkData->_stats.send_ShortWrite++;
        parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "short write");
        return -1;
    }

    return 0;
}