CCNxCodecNetworkBufferIoVec * athenaTransportLinkModule_GetMessageIoVector(CCNxMetaMessage *message) { CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(message); // If there was no io vector present, check for a buffer and convert that into an iovec if (iovec == NULL) { PARCBuffer *buffer = ccnxWireFormatMessage_GetWireFormatBuffer(message); if (buffer == NULL) { // if there's no iovec or buffer, encode the message and return the iovec athena_EncodeMessage(message); iovec = ccnxWireFormatMessage_GetIoVec(message); iovec = ccnxCodecNetworkBufferIoVec_Acquire(iovec); } else { CCNxCodecNetworkBuffer *netbuff = ccnxCodecNetworkBuffer_Create(&ParcMemoryMemoryBlock, NULL); assertNotNull(netbuff, "Null network buffer allocation"); parcBuffer_SetPosition(buffer, 0); ccnxCodecNetworkBuffer_PutBuffer(netbuff, buffer); iovec = ccnxCodecNetworkBuffer_CreateIoVec(netbuff); ccnxCodecNetworkBuffer_Release(&netbuff); } } else { iovec = ccnxCodecNetworkBufferIoVec_Acquire(iovec); } return iovec; }
PARCBuffer * athenaTransportLinkModule_CreateMessageBuffer(CCNxMetaMessage *message) { PARCBuffer *buffer = ccnxWireFormatMessage_GetWireFormatBuffer(message); // If there is no PARCBuffer present, check for an IO vector and convert that into a contiguous buffer. if (buffer == NULL) { CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(message); if (iovec == NULL) { // if there's no iovec or buffer, encode the message and return the iovec athena_EncodeMessage(message); iovec = ccnxWireFormatMessage_GetIoVec(message); } assertNotNull(iovec, "Null io vector"); size_t iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec); const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec); // If it's a single vector wrap it in a buffer to avoid a copy if (iovcnt == 1) { buffer = parcBuffer_Wrap(array[0].iov_base, array[0].iov_len, 0, array[0].iov_len); } else { size_t totalbytes = 0; for (int i = 0; i < iovcnt; i++) { totalbytes += array[i].iov_len; } buffer = parcBuffer_Allocate(totalbytes); for (int i = 0; i < iovcnt; i++) { parcBuffer_PutArray(buffer, array[i].iov_len, array[i].iov_base); } parcBuffer_Flip(buffer); } } else { buffer = parcBuffer_Acquire(buffer); } return buffer; }
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); }
static int _UDPSend(AthenaTransportLink *athenaTransportLink, CCNxMetaMessage *ccnxMetaMessage) { struct _UDPLinkData *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)); } // Get a wire format buffer and write it out. PARCBuffer *wireFormatBuffer = ccnxWireFormatMessage_GetWireFormatBuffer(ccnxMetaMessage); if (wireFormatBuffer == NULL) { CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(ccnxMetaMessage); assertNotNull(iovec, "Null io vector"); size_t iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec); const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec); // If it's a single vector wrap it in a buffer to avoid a copy if (iovcnt == 1) { wireFormatBuffer = parcBuffer_Wrap(array[0].iov_base, array[0].iov_len, 0, array[0].iov_len); } else { size_t totalbytes = 0; for (int i = 0; i < iovcnt; i++) { totalbytes += array[i].iov_len; } wireFormatBuffer = parcBuffer_Allocate(totalbytes); for (int i = 0; i < iovcnt; i++) { parcBuffer_PutArray(wireFormatBuffer, array[i].iov_len, array[i].iov_base); } parcBuffer_Flip(wireFormatBuffer); } } else { wireFormatBuffer = parcBuffer_Acquire(wireFormatBuffer); } size_t length = parcBuffer_Limit(wireFormatBuffer); char *buffer = parcBuffer_Overlay(wireFormatBuffer, length); if (linkData->link.mtu) { if (length > linkData->link.mtu) { errno = EMSGSIZE; parcBuffer_Release(&wireFormatBuffer); return -1; } } parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "sending message (size=%d)", length); ssize_t writeCount = 0; #ifdef LINUX_IGNORESIGPIPE writeCount = sendto(linkData->fd, buffer, length, MSG_NOSIGNAL, (struct sockaddr *) &linkData->link.peerAddress, linkData->link.peerAddressLength); #else writeCount = sendto(linkData->fd, buffer, length, 0, (struct sockaddr *) &linkData->link.peerAddress, linkData->link.peerAddressLength); #endif // on error close the link, else return to retry a zero write if (writeCount == -1) { if (errno == EPIPE) { athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Error); } parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "send error (%s)", strerror(errno)); parcBuffer_Release(&wireFormatBuffer); return -1; } // Short write if (writeCount != length) { linkData->_stats.receive_ShortWrite++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "short write"); parcBuffer_Release(&wireFormatBuffer); return -1; } parcBuffer_Release(&wireFormatBuffer); return 0; }