/** * 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; }
void parcJSONParser_Advance(PARCJSONParser *parser, long bytes) { parcJSONParser_OptionalAssertValid(parser); parcBuffer_SetPosition(parser->buffer, parcBuffer_Position(parser->buffer) + bytes); }
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; }
PARCBuffer * parcBuffer_Slice(const PARCBuffer *original) { PARCBuffer *result = _parcBuffer_getInstance(); if (result != NULL) { _parcBuffer_Init(result, parcByteArray_Acquire(original->array), original->arrayOffset + parcBuffer_Position(original), 0, parcBuffer_Limit(original) - parcBuffer_Position(original), parcBuffer_Limit(original) - parcBuffer_Position(original)); _optionalAssertInvariants(result); } return result; }
LONGBOW_TEST_CASE(Specialization, test_hmac_sha512) { HMAC_CTX ctx; char key[] = "apple_pie_is_good"; int fd; uint8_t to_digest_buffer[MAXPATHLEN]; ssize_t to_digest_length; uint8_t true_hmac_buffer[MAXPATHLEN]; ssize_t true_hmac_length; LONGBOW_STOP_DEPRECATED_WARNINGS HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, sizeof(key), EVP_sha512(), NULL); LONGBOW_START_DEPRECATED_WARNINGS fd = open("test_random_bytes", O_RDONLY); assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); to_digest_length = read(fd, to_digest_buffer, sizeof(to_digest_buffer)); assertTrue(to_digest_length > 0, "Could not read input file: %s", strerror(errno)); close(fd); fd = open("test_random_bytes.hmac_sha512", O_RDONLY); assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); true_hmac_length = read(fd, true_hmac_buffer, sizeof(true_hmac_buffer)); assertTrue(true_hmac_length > 0, "Could not read input file: %s", strerror(errno)); close(fd); _hmacInit(&ctx); _hmacUpdate(&ctx, to_digest_buffer, to_digest_length); PARCBuffer *output = _hmacFinalize(&ctx); assertTrue(parcBuffer_Position(output) == true_hmac_length, "hmac wrong length, expected %zu got %zu", true_hmac_length, parcBuffer_Position(output)); assertTrue(memcmp(parcByteArray_Array(parcBuffer_Array(output)), true_hmac_buffer, true_hmac_length) == 0, "hmac values did not match"); LONGBOW_STOP_DEPRECATED_WARNINGS HMAC_cleanup(&ctx); LONGBOW_START_DEPRECATED_WARNINGS parcBuffer_Release(&output); }
size_t parcBuffer_FindUint8(const PARCBuffer *buffer, uint8_t byte) { for (size_t i = parcBuffer_Position(buffer); i < parcBuffer_Limit(buffer); i++) { if (parcBuffer_GetAtIndex(buffer, i) == byte) { return i; } } return SIZE_MAX; }
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_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; }
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; }
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; }
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; }
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; }
PARCBuffer * parcBuffer_Copy(const PARCBuffer *original) { parcBuffer_OptionalAssertValid(original); PARCBuffer *result = _parcBuffer_getInstance(); if (result != NULL) { PARCByteArray *array = parcByteArray_Copy(original->array); if (array != NULL) { _parcBuffer_Init(result, array, parcBuffer_ArrayOffset(original), parcBuffer_Position(original), parcBuffer_Limit(original), parcBuffer_Capacity(original)); } else { parcBuffer_Release(&result); } } 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; }
void * parcBuffer_Overlay(PARCBuffer *buffer, size_t length) { parcBuffer_OptionalAssertValid(buffer); _trapIfBufferUnderflow(buffer, length); uint8_t *result = parcByteArray_AddressOfIndex(buffer->array, _effectiveIndex(buffer, parcBuffer_Position(buffer))); buffer->position += length; return result; }
uint8_t parcBuffer_PeekByte(const PARCBuffer *buffer) { return parcBuffer_GetAtIndex(buffer, parcBuffer_Position(buffer)); }
// // 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; }
static inline size_t _effectivePosition(const PARCBuffer *buffer) { return buffer->arrayOffset + parcBuffer_Position(buffer); }