bool ccnxCodecSchemaV1FixedHeaderDecoder_Decode(CCNxCodecTlvDecoder *decoder, CCNxTlvDictionary *packetDictionary) { if (ccnxCodecTlvDecoder_EnsureRemaining(decoder, _fixedHeaderBytes)) { PARCBuffer *buffer = ccnxCodecTlvDecoder_GetValue(decoder, _fixedHeaderBytes); bool success = ccnxTlvDictionary_PutBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader, buffer); // validation parcBuffer_SetPosition(buffer, _fixedHeader_VersionOffset); uint8_t version = parcBuffer_GetUint8(buffer); parcBuffer_SetPosition(buffer, _fixedHeader_PacketLengthOffset); uint16_t packetLength = parcBuffer_GetUint16(buffer); parcBuffer_SetPosition(buffer, _fixedHeader_HopLimitOffset); uint8_t hopLimit = parcBuffer_GetUint8(buffer); parcBuffer_SetPosition(buffer, _fixedHeader_HeaderLengthOffset); uint8_t headerLength = parcBuffer_GetUint8(buffer); if (version != 1) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_VERSION, __func__, __LINE__, _fixedHeader_VersionOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } else if (packetLength < _fixedHeaderBytes) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETLENGTH_TOO_SHORT, __func__, __LINE__, _fixedHeader_PacketTypeOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } else if (headerLength < _fixedHeaderBytes) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_HEADERLENGTH_TOO_SHORT, __func__, __LINE__, _fixedHeader_HeaderLengthOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } else if (packetLength < headerLength) { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_PACKETLENGTHSHORTER, __func__, __LINE__, _fixedHeader_PacketTypeOffset); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); success = false; } // decoder now points to just past the fixed header parcBuffer_Release(&buffer); // Set the hoplimit in the dictionary. ccnxTlvDictionary_PutInteger(packetDictionary, CCNxCodecSchemaV1TlvDictionary_MessageFastArray_HOPLIMIT, hopLimit); return success; } else { CCNxCodecError *error = ccnxCodecError_Create(TLV_ERR_DECODE, __func__, __LINE__, ccnxCodecTlvDecoder_Position(decoder)); ccnxCodecTlvDecoder_SetError(decoder, error); ccnxCodecError_Release(&error); return false; } }
// // Receive a message from the specified link. // static CCNxMetaMessage * _ETHReceiveMessage(AthenaTransportLink *athenaTransportLink, struct ether_addr *peerAddress, socklen_t *peerAddressLength) { struct _ETHLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink); CCNxMetaMessage *ccnxMetaMessage = NULL; AthenaTransportLinkEvent events = 0; PARCBuffer *message = athenaEthernet_Receive(linkData->athenaEthernet, -1, &events); if (message == NULL) { return NULL; } // Mark any pending events if (events) { athenaTransportLink_SetEvent(athenaTransportLink, events); } // Map the header struct ether_header *header = parcBuffer_Overlay(message, sizeof(struct ether_header)); // If the destination does not match my address, drop the message if (memcmp(&linkData->link.myAddress, header->ether_dhost, ETHER_ADDR_LEN * sizeof(uint8_t)) != 0) { linkData->_stats.receive_NoLinkDestination++; parcBuffer_Release(&message); return NULL; } assertTrue(header->ether_type == htons(CCNX_ETHERTYPE), "Unexpected ether type %x", header->ether_type); // Set peerAddress from header source address *peerAddressLength = ETHER_ADDR_LEN * sizeof(uint8_t); memcpy(peerAddress, header->ether_shost, *peerAddressLength); parcBuffer_SetPosition(message, sizeof(struct ether_header)); PARCBuffer *wireFormatBuffer = parcBuffer_Slice(message); parcBuffer_Release(&message); parcBuffer_SetPosition(wireFormatBuffer, 0); // Construct, and return a ccnxMetaMessage from the wire format buffer. ccnxMetaMessage = ccnxMetaMessage_CreateFromWireFormatBuffer(wireFormatBuffer); if (ccnxMetaMessage == NULL) { linkData->_stats.receive_DecodeFailed++; parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "Failed to decode message from received packet."); } else if (ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage) == CCNxTlvDictionary_SchemaVersion_V0) { parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "received deprecated version %d message\n", ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage)); } parcBuffer_Release(&wireFormatBuffer); return ccnxMetaMessage; }
/** * Given a CCNxName, a directory path, and a requested chunk number, create a directory listing and return the specified * chunk of the directory listing as the payload of a newly created CCNxContentObject. * The new CCnxContentObject must eventually be released by calling ccnxContentObject_Release(). * * @param [in] name The CCNxName to use when creating the new CCNxContentObject. * @param [in] directoryPath The directory whose contents are being listed. * @param [in] requestedChunkNumber The number of the requested chunk from the complete directory listing. * * @return A new CCNxContentObject instance containing the request chunk of the directory listing. */ static CCNxContentObject * _createListResponse(CCNxName *name, const char *directoryPath, uint64_t requestedChunkNumber) { CCNxContentObject *result = NULL; PARCBuffer *directoryList = tutorialFileIO_CreateDirectoryListing(directoryPath); uint64_t totalChunksInDirList = _getNumberOfChunksRequired(parcBuffer_Limit(directoryList), tutorialCommon_ChunkSize); if (requestedChunkNumber < totalChunksInDirList) { // Set the buffer's position to the start of the desired chunk. parcBuffer_SetPosition(directoryList, (requestedChunkNumber * tutorialCommon_ChunkSize)); // See if we have more than 1 chunk's worth of data to in the buffer. If so, set the buffer's limit // to the end of the chunk. size_t chunkLen = parcBuffer_Remaining(directoryList); if (chunkLen > tutorialCommon_ChunkSize) { parcBuffer_SetLimit(directoryList, parcBuffer_Position(directoryList) + tutorialCommon_ChunkSize); } printf("tutorialServer: Responding to 'list' command with chunk %ld/%ld\n", (unsigned long) requestedChunkNumber, (unsigned long) totalChunksInDirList); // Calculate the final chunk number uint64_t finalChunkNumber = (totalChunksInDirList > 0) ? totalChunksInDirList - 1 : 0; // the final chunk, 0-based // At this point, dirListBuf has its position and limit set to the beginning and end of the // specified chunk. result = _createContentObject(name, directoryList, finalChunkNumber); } parcBuffer_Release(&directoryList); return result; }
CCNxNameSegment * ccnxNameSegment_ParseURISegment(const PARCURISegment *uriSegment) { CCNxNameSegment *result = NULL; PARCBuffer *buffer = parcURISegment_GetBuffer(uriSegment); size_t originalPosition = parcBuffer_Position(buffer); CCNxNameLabel *label = ccnxNameLabel_Parse(buffer); if (ccnxNameLabel_IsValid(label)) { PARCBuffer *value = parcBuffer_Slice(buffer); CCNxNameLabelType nameType = ccnxNameLabel_GetType(label); if (nameType != CCNxNameLabelType_Unknown) { result = ccnxNameSegment_CreateLabelValue(label, value); } ccnxNameLabel_Release(&label); parcBuffer_Release(&value); parcBuffer_SetPosition(buffer, originalPosition); } return result; }
void parcJSONParser_Advance(PARCJSONParser *parser, long bytes) { parcJSONParser_OptionalAssertValid(parser); parcBuffer_SetPosition(parser->buffer, parcBuffer_Position(parser->buffer) + bytes); }
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 * athenaEthernet_Receive(AthenaEthernet *athenaEthernet, int timeout, AthenaTransportLinkEvent *events) { // Allocate, and read, a new BPF buffer if no packets are currently pending in an old one if (athenaEthernet->bpfBuffer == NULL) { athenaEthernet->bpfBuffer = parcBuffer_Allocate(athenaEthernet->etherBufferLength); uint8_t *buffer = parcBuffer_Overlay(athenaEthernet->bpfBuffer, 0); athenaEthernet->readCount = read(athenaEthernet->fd, buffer, athenaEthernet->etherBufferLength); if (athenaEthernet->readCount == -1) { if ((errno == EAGAIN) || (errno == EINTR)) { parcLog_Info(athenaEthernet->log, "Ethernet read retry"); return NULL; } parcLog_Error(athenaEthernet->log, "recv: %s", strerror(errno)); *events = AthenaTransportLinkEvent_Error; parcBuffer_Release(&athenaEthernet->bpfBuffer); return NULL; } parcLog_Debug(athenaEthernet->log, "received bpf packet (size=%d)", athenaEthernet->readCount); } // Obtain the current position in the BPF buffer to return a message from size_t position = parcBuffer_Position(athenaEthernet->bpfBuffer); // Read the BPF header and seek past it struct bpf_hdr *bpfhdr = parcBuffer_Overlay(athenaEthernet->bpfBuffer, sizeof(struct bpf_hdr)); parcBuffer_SetLimit(athenaEthernet->bpfBuffer, position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen); parcBuffer_SetPosition(athenaEthernet->bpfBuffer, position + bpfhdr->bh_hdrlen); parcLog_Debug(athenaEthernet->log, "received message (size=%d)", bpfhdr->bh_datalen); // Slice a new PARCBuffer with the message to send up. PARCBuffer *wireFormatBuffer = parcBuffer_Slice(athenaEthernet->bpfBuffer); // If there's another packet in the buffer, position it and flag a receive event if ((athenaEthernet->readCount - (position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen)) != 0) { parcBuffer_SetLimit(athenaEthernet->bpfBuffer, athenaEthernet->readCount); parcBuffer_SetPosition(athenaEthernet->bpfBuffer, BPF_WORDALIGN(position + bpfhdr->bh_hdrlen + bpfhdr->bh_datalen)); // Mark a receive event for this packet *events = AthenaTransportLinkEvent_Receive; } else { parcBuffer_Release(&athenaEthernet->bpfBuffer); } return wireFormatBuffer; }
PARCBuffer * ccnxInterestPayloadId_GetValue(const CCNxInterestPayloadId *id) { PARCBuffer *data = ccnxNameSegment_GetValue(id->nameSegment); parcBuffer_Rewind(data); parcBuffer_SetPosition(data, 1); return data; }
PARCBuffer * parcBuffer_Clear(PARCBuffer *buffer) { parcBuffer_SetPosition(buffer, 0); parcBuffer_SetLimit(buffer, parcBuffer_Capacity(buffer)); _discardMark(buffer); return buffer; }
LONGBOW_TEST_CASE(Global, parcNetwork_LinkAddress_Parse_dots) { char *expected = "link://0123.4567.89ab"; PARCBuffer *address = parcNetwork_ParseLinkAddress(expected); PARCBuffer *e = parcBuffer_Wrap((uint8_t []) { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab }, 6, 0, 6); parcBuffer_SetPosition(address, 0); parcBuffer_SetPosition(e, 0); parcBuffer_SetLimit(address, 6); parcBuffer_SetLimit(e, 6); assertTrue(parcBuffer_Equals(address, e), "Expected result failed."); parcBuffer_Release(&e); parcBuffer_Release(&address); }
PARCBuffer * parcBuffer_PutArray(PARCBuffer *buffer, size_t arrayLength, const uint8_t array[arrayLength]) { parcBuffer_OptionalAssertValid(buffer); assertTrue(parcBuffer_Remaining(buffer) >= arrayLength, "Buffer overflow"); parcByteArray_PutBytes(buffer->array, _effectivePosition(buffer), arrayLength, array); return parcBuffer_SetPosition(buffer, parcBuffer_Position(buffer) + arrayLength); }
PARCBuffer * parcBuffer_AllocateCString(const char *string) { size_t length = strlen(string); PARCBuffer *buffer = parcBuffer_Allocate(length + 1); parcBuffer_PutArray(buffer, length, (const uint8_t *) string); parcBuffer_PutUint8(buffer, 0); parcBuffer_SetPosition(buffer, buffer->position - 1); parcBuffer_Flip(buffer); return buffer; }
bool parcBuffer_SkipOver(PARCBuffer *buffer, size_t length, const uint8_t bytesToSkipOver[length]) { while (parcBuffer_Remaining(buffer) > 0) { uint8_t character = parcBuffer_GetUint8(buffer); if (memchr(bytesToSkipOver, character, length) == NULL) { parcBuffer_SetPosition(buffer, parcBuffer_Position(buffer) - 1); return true; } } return false; }
int ccnxCodecSchemaV1FixedHeaderDecoder_GetFlags(CCNxTlvDictionary *packetDictionary) { PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader); if (fixedHeader != NULL) { parcBuffer_SetPosition(fixedHeader, _fixedHeader_FlagsOffset); uint8_t flags = parcBuffer_GetUint8(fixedHeader); return flags; } return -1; }
int ccnxCodecSchemaV1FixedHeaderDecoder_GetPacketLength(CCNxTlvDictionary *packetDictionary) { PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader); if (fixedHeader != NULL) { parcBuffer_SetPosition(fixedHeader, _fixedHeader_PacketLengthOffset); uint16_t payloadLength = parcBuffer_GetUint16(fixedHeader); return payloadLength; } return -1; }
PARCBuffer * parcBuffer_PutBuffer(PARCBuffer *result, const PARCBuffer *buffer) { parcBuffer_OptionalAssertValid(buffer); assertTrue(parcBuffer_Remaining(result) >= parcBuffer_Remaining(buffer), "Buffer overflow. %zd bytes remaining, %zd required.", parcBuffer_Remaining(result), parcBuffer_Remaining(buffer)); size_t length = parcBuffer_Remaining(buffer); parcByteArray_ArrayCopy(result->array, _effectivePosition(result), buffer->array, _effectivePosition(buffer), length); parcBuffer_SetPosition(result, parcBuffer_Position(result) + length); return result; }
static void * _ccnxChunker_NextFromBuffer(PARCBufferChunker *chunker, _ChunkerState *state) { size_t chunkSize = state->nextChunkSize; parcBuffer_SetPosition(chunker->data, state->position); PARCBuffer *slice = parcBuffer_CreateFromArray(parcBuffer_Overlay(chunker->data, chunkSize), chunkSize); slice = parcBuffer_Flip(slice); _advanceState(chunker, state); return slice; }
bool parcBuffer_SkipTo(PARCBuffer *buffer, size_t length, const uint8_t bytesToSkipTo[length]) { bool result = false; while (parcBuffer_Remaining(buffer) > 0) { uint8_t character = parcBuffer_GetUint8(buffer); if (memchr(bytesToSkipTo, character, length) != NULL) { parcBuffer_SetPosition(buffer, parcBuffer_Position(buffer) - 1); result = true; break; } } return result; }
int ccnxCodecSchemaV1FixedHeaderDecoder_GetHeaderLength(CCNxTlvDictionary *packetDictionary) { int length = -1; PARCBuffer *fixedHeader = ccnxTlvDictionary_GetBuffer(packetDictionary, CCNxCodecSchemaV1TlvDictionary_HeadersFastArray_FixedHeader); if (fixedHeader != NULL) { parcBuffer_SetPosition(fixedHeader, _fixedHeader_HeaderLengthOffset); uint8_t headerLength = parcBuffer_GetUint8(fixedHeader); // 8 is the minimum size of headerLength if (headerLength >= _fixedHeaderBytes) { length = headerLength; } } return length; }
uint64_t parcBuffer_ParseDecimalNumber(PARCBuffer *buffer) { char *bytes = parcBuffer_Overlay(buffer, 0); int start = 0; unsigned count = 0; uint64_t result = 0; for (int i = start; i < parcBuffer_Remaining(buffer) && isdigit(bytes[i]); i++) { result = (result * 10) + _digittoint(bytes[i]); count++; } parcBuffer_SetPosition(buffer, parcBuffer_Position(buffer) + count); return result; }
static char * _toString(const PARCLogEntry *entry) { PARCBufferComposer *composer = parcBufferComposer_Create(); parcBufferComposer_Format(composer, "%ld.%06d %d ", (long) entry->timeStamp.tv_sec, (int) entry->timeStamp.tv_usec, entry->level); size_t position = parcBuffer_Position(entry->payload); parcBufferComposer_PutBuffer(composer, entry->payload); parcBuffer_SetPosition(entry->payload, position); PARCBuffer *buffer = parcBufferComposer_GetBuffer(composer); parcBuffer_Rewind(buffer); char *result = parcBuffer_ToString(buffer); parcBufferComposer_Release(&composer); return result; }
uint64_t parcBuffer_ParseHexNumber(PARCBuffer *buffer) { char *bytes = parcBuffer_Overlay(buffer, 0); int start = 0; if (parcBuffer_Remaining(buffer) > 2) { if (bytes[0] == '0' && bytes[1] == 'x') { start = 2; } } unsigned count = 0; uint64_t result = 0; for (int i = start; i < parcBuffer_Remaining(buffer) && isxdigit(bytes[i]); i++) { result = (result * 16) + _digittoint(bytes[i]); count++; } parcBuffer_SetPosition(buffer, parcBuffer_Position(buffer) + start + count); return result; }
PARCBuffer * tutorialFileIO_GetFileChunk(const char *fileName, size_t chunkSize, uint64_t chunkNum) { FILE *file = fopen(fileName, "r"); assertNotNull(file, "Could not open file '%s' - stopping.", fileName); // When PARCFileInputStream has a Seek() function, consider using it instead of // the following approach. // Seek to the location of the desired chunk in the file. assertTrue(fseek(file, chunkSize * chunkNum, SEEK_SET) == 0, "Could not seek to desired chunk"); // If we're here, we were able to seek to the start of the desired chunk PARCBuffer *result = parcBuffer_Allocate(chunkSize); size_t numberOfBytesNeeded = chunkSize; size_t numberOfBytesRead = 0; // # bytes read in each read. size_t totalNumberOfBytesRead = 0; // Overall # of bytes read // Read until we get the required number of bytes. while (numberOfBytesNeeded > 0 && (numberOfBytesRead = fread(parcBuffer_Overlay(result, 0), 1, numberOfBytesNeeded, file)) > 0) { numberOfBytesNeeded -= numberOfBytesRead; parcBuffer_SetPosition(result, parcBuffer_Position(result) + numberOfBytesRead); totalNumberOfBytesRead += numberOfBytesRead; } parcBuffer_SetLimit(result, totalNumberOfBytesRead); parcBuffer_Flip(result); fclose(file); return result; }
// // Receive a message from the specified link. // static CCNxMetaMessage * _UDPReceiveMessage(AthenaTransportLink *athenaTransportLink, struct sockaddr_in *peerAddress, socklen_t *peerAddressLength) { struct _UDPLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink); CCNxMetaMessage *ccnxMetaMessage = NULL; size_t messageLength; // If an MTU has been set, allocate a buffer of that size to avoid having to peek at the message, // othersize derive the link from the header and allocate a buffer based on the message size. if ((messageLength = linkData->link.mtu) == 0) { messageLength = _messageLengthFromHeader(athenaTransportLink, linkData); if (messageLength <= 0) { return NULL; } } PARCBuffer *wireFormatBuffer = parcBuffer_Allocate(messageLength); char *buffer = parcBuffer_Overlay(wireFormatBuffer, 0); *peerAddressLength = (socklen_t) sizeof(struct sockaddr_in); ssize_t readCount = recvfrom(linkData->fd, buffer, messageLength, 0, (struct sockaddr *) peerAddress, peerAddressLength); // On error, just return and retry. if (readCount == -1) { linkData->_stats.receive_ReadError++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "read error (%s)", strerror(errno)); parcBuffer_Release(&wireFormatBuffer); return NULL; } // A zero read means either no more data is currently available or our peer hungup. // Just return to retry as we'll detect EOF when we come back at the top of UDPReceive if (readCount == 0) { parcBuffer_Release(&wireFormatBuffer); return NULL; } // If it was it a short read just return to retry later. while (readCount < messageLength) { linkData->_stats.receive_ShortRead++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "short read error (%s)", strerror(errno)); parcBuffer_Release(&wireFormatBuffer); return NULL; } parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "received message (size=%d)", readCount); parcBuffer_SetPosition(wireFormatBuffer, parcBuffer_Position(wireFormatBuffer) + readCount); parcBuffer_Flip(wireFormatBuffer); // Construct, and return a ccnxMetaMessage from the wire format buffer. ccnxMetaMessage = ccnxMetaMessage_CreateFromWireFormatBuffer(wireFormatBuffer); if (ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage) == CCNxTlvDictionary_SchemaVersion_V0) { parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "received deprecated version %d message\n", ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage)); } if (ccnxMetaMessage == NULL) { linkData->_stats.receive_DecodeFailed++; parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "Failed to decode message from received packet."); } parcBuffer_Release(&wireFormatBuffer); return ccnxMetaMessage; }
/** * Run the consumer to fetch the specified file. Save it to disk once transferred. * * @param [in] target Name of the content to request. * @param [in] outFile Name of the file to which the buffer will be written. */ static int _ccnxFileRepoClient_Run(char *target, char *outFile) { parcSecurity_Init(); PARCLog *log = _ccnxFileRepoClient_CreateLogger(); CCNxPortalFactory *factory = _setupConsumerPortalFactory(); CCNxPortal *portal = ccnxPortalFactory_CreatePortal(factory, ccnxPortalRTA_Message); assertNotNull(portal, "Expected a non-null CCNxPortal pointer."); CCNxName *name = ccnxName_CreateFromCString(target); CCNxInterest *interest = ccnxInterest_CreateSimple(name); CCNxMetaMessage *message = ccnxMetaMessage_CreateFromInterest(interest); if (ccnxPortal_Send(portal, message, CCNxStackTimeout_Never)) { while (ccnxPortal_IsError(portal) == false) { CCNxMetaMessage *response = ccnxPortal_Receive(portal, CCNxStackTimeout_Never); if (response != NULL) { if (ccnxMetaMessage_IsManifest(response)) { parcLog_Info(log, "Received root manifest. Beginning to retrieve the content."); // Extract the manifest and instantiate a new fetcher for it CCNxManifest *root = ccnxMetaMessage_GetManifest(response); CCNxFileRepoManifestFetcher *fetcher = ccnxFileRepoManifestFetcher_Create(portal, root); // Initialize the file offset and I/O buffer size_t fileOffset = 0; PARCBuffer *chunkBuffer = parcBuffer_Allocate(ccnxFileRepoCommon_ClientBufferSize); // Start reading from the manifest until done bool done = false; while (!done) { // Reset the buffer information parcBuffer_SetPosition(chunkBuffer, 0); parcBuffer_SetLimit(chunkBuffer, ccnxFileRepoCommon_ClientBufferSize); // Fill the buffer with data from the manifest done = ccnxFileRepoManifestFetcher_FillBuffer(fetcher, chunkBuffer); parcBuffer_Flip(chunkBuffer); // Write the buffer to the file size_t totalSize = parcBuffer_Remaining(chunkBuffer); _ccnxFileRepoClient_AppendBufferToFile(outFile, chunkBuffer, fileOffset); fileOffset += totalSize; // Flip the buffer back around for writing parcBuffer_Flip(chunkBuffer); } parcBuffer_Release(&chunkBuffer); break; } else if (ccnxMetaMessage_IsContentObject(response)) { parcLog_Info(log, "Received a content object. Dump the payload and exit."); CCNxContentObject *contentObject = ccnxMetaMessage_GetContentObject(response); PARCBuffer *payload = ccnxContentObject_GetPayload(contentObject); _ccnxFileRepoClient_AppendBufferToFile(outFile, payload, 0); break; } } ccnxMetaMessage_Release(&response); } } ccnxPortal_Release(&portal); ccnxPortalFactory_Release(&factory); parcSecurity_Fini(); return 0; }
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 = athenaTransportLinkModule_GetMessageBuffer(ccnxMetaMessage); parcBuffer_SetPosition(wireFormatBuffer, 0); 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 == EAGAIN) || (errno == EINTR)) { linkData->_stats.send_SendRetry++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "send retry (%s)", strerror(errno)); } else { 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.send_ShortWrite++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "short write"); parcBuffer_Release(&wireFormatBuffer); return -1; } parcBuffer_Release(&wireFormatBuffer); return 0; }