// A signum function to compare two PARCBuffers by length of buffer. static int _compareTwoBuffersByLength(const PARCObject *buf1, const PARCObject *buf2) { size_t size1 = parcBuffer_Limit((PARCBuffer *) buf1); size_t size2 = parcBuffer_Limit((PARCBuffer *) buf2); if (size1 > size2) { return 1; } else if (size2 > size1) { return -1; } return 0; }
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; }
/** * 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; }
PARCBuffer * parcBuffer_PutAtIndex(PARCBuffer *buffer, size_t index, uint8_t value) { parcBuffer_OptionalAssertValid(buffer); assertTrue(_effectiveIndex(buffer, index) < parcBuffer_Limit(buffer), "Buffer overflow"); parcByteArray_PutByte(buffer->array, _effectiveIndex(buffer, index), value); return buffer; }
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; }
LONGBOW_TEST_CASE(Global, parcBufferComposer_Allocate) { size_t size = 10; PARCBufferComposer *composer = parcBufferComposer_Allocate(size); PARCBuffer *buffer = parcBufferComposer_GetBuffer(composer); assertNotNull(composer, "PARCBufferComposer instance should be non-NULL."); assertTrue(parcBuffer_Limit(buffer) == size, "PARCBufferComposer instance's internal PARCBuffer limit must be %zu: %zu", size, parcBuffer_Limit(buffer)); parcBufferComposer_Release(&composer); }
static size_t _calculateSizeOfContentObject(const CCNxContentObject *contentObject) { size_t result = 0; char *nameAsString = ccnxName_ToString(ccnxContentObject_GetName(contentObject)); result += strlen(nameAsString); parcMemory_DeallocateImpl((void **) &nameAsString); PARCBuffer *payload = ccnxContentObject_GetPayload(contentObject); if (payload != NULL) { result += parcBuffer_Limit(payload); } return result; }
PARCBuffer * parcBuffer_Duplicate(const PARCBuffer *original) { PARCBuffer *result = _parcBuffer_getInstance(); if (result != NULL) { _parcBuffer_Init(result, parcByteArray_Acquire(original->array), original->arrayOffset, original->position, parcBuffer_Limit(original), original->capacity); _optionalAssertInvariants(result); } return result; }
static PARCBufferComposer * _uriSegment_BuildString(const PARCURISegment *segment, PARCBufferComposer *composer) { assertNotNull(composer, "Parameter must be a non-null pointer to a PARCBufferComposer."); for (size_t i = 0; i < parcBuffer_Limit(segment->buffer) && composer != NULL; i++) { unsigned char c = parcBuffer_GetAtIndex(segment->buffer, i); if (uriPlainSegmentChar(c)) { parcBufferComposer_PutChar(composer, c); } else { parcBufferComposer_PutChar(composer, '%'); parcBufferComposer_PutChar(composer, _toHexDigit(c >> 4)); parcBufferComposer_PutChar(composer, _toHexDigit(c)); } } return composer; }
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; }
static inline void _trapIfIndexExceedsLimit(const PARCBuffer *buffer, const size_t index) { trapOutOfBoundsIf(index > buffer->limit, "PARCBuffer limit at %zd, attempted to access at %zd", parcBuffer_Limit(buffer), index); }
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; }
LONGBOW_TEST_CASE(Global, ccnxCodecSchemaV1ManifestDecoder_DecodeHashGroupMetadata) { // Re-build the expected metadata from the manifest CCNxName *groupLocator = ccnxName_CreateFromCString("ccnx:/locator"); PARCBuffer *digest = parcBuffer_Allocate(16); for (size_t i = 0; i < parcBuffer_Limit(digest); i++) { parcBuffer_PutUint8(digest, 0); } parcBuffer_Flip(digest); size_t entrySize = 1; size_t dataSize = 2; size_t blockSize = 3; size_t treeHeight = 4; // Compute the expected size of this metadata group. size_t metadataSize = 4 * (4 + 8) + 4 + parcBuffer_Limit(digest) + 4 + strlen("ccnx:/locator"); // See test_ccnxCodecSchemaV1_ManifestEncoder.c for the packet construction details. uint8_t rawMetadata[89] = { 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroup_Metadata, 0x00, metadataSize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_Locator, 0x00, strlen("ccnx:/locator"), 'c', 'c', 'n', 'x', ':', '/', 'l', 'o', 'c', 'a', 't', 'o', 'r', 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_DataSize, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, dataSize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_BlockSize, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, blockSize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_EntrySize, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, entrySize, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_TreeHeight, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, treeHeight, 0x00, CCNxCodecSchemaV1Types_CCNxManifestHashGroupMetadata_OverallDataSha256, 0x00, parcBuffer_Remaining(digest), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; PARCBuffer *wireFormat = parcBuffer_Flip(parcBuffer_CreateFromArray(rawMetadata, sizeof(rawMetadata))); // Create the encoder and swallow the top level container CCNxCodecTlvDecoder *decoder = ccnxCodecTlvDecoder_Create(wireFormat); ccnxCodecTlvDecoder_GetType(decoder); // swallow type uint16_t length = ccnxCodecTlvDecoder_GetLength(decoder); // Decode the metadata CCNxManifestHashGroup *group = ccnxManifestHashGroup_Create(); bool result = _decodeHashGroupMetadata(decoder, group, length); assertTrue(result, "Expected hash group metadata to be decoded correctly."); const CCNxName *actualLocator = ccnxManifestHashGroup_GetLocator(group); size_t actualEntrySize = ccnxManifestHashGroup_GetEntrySize(group); size_t actualDataSize = ccnxManifestHashGroup_GetDataSize(group); size_t actualBlockSize = ccnxManifestHashGroup_GetBlockSize(group); size_t actualTreeHeight = ccnxManifestHashGroup_GetTreeHeight(group); const PARCBuffer *actualDigest = ccnxManifestHashGroup_GetOverallDataDigest(group); assertTrue(ccnxName_Equals(groupLocator, actualLocator), "Expected decoded locator to equal %s, got %s", ccnxName_ToString(groupLocator), ccnxName_ToString(actualLocator)); assertTrue(entrySize == actualEntrySize, "Expected %zu entry size, got %zu", entrySize, actualEntrySize); assertTrue(dataSize == actualDataSize, "Expected %zu data size, got %zu", dataSize, actualDataSize); assertTrue(blockSize == actualBlockSize, "Expected %zu block size, got %zu", blockSize, actualBlockSize); assertTrue(treeHeight == actualTreeHeight, "Expected %zu tree height, got %zu", treeHeight, actualTreeHeight); assertTrue(parcBuffer_Equals(digest, actualDigest), "Expected %s digest, got %s", parcBuffer_ToHexString(digest), parcBuffer_ToHexString(actualDigest)); parcBuffer_Release(&digest); ccnxName_Release(&groupLocator); ccnxManifestHashGroup_Release(&group); ccnxCodecTlvDecoder_Destroy(&decoder); parcBuffer_Release(&wireFormat); }
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; }
// ============================================================= LONGBOW_STOP_DEPRECATED_WARNINGS // ============================================================= bool parcPkcs12KeyStore_CreateFile( const char *filename, const char *password, const char *subjectName, unsigned keyLength, unsigned validityDays) { parcSecurity_AssertIsInitialized(); bool result = false; PARCCertificateFactory *factory = parcCertificateFactory_Create(PARCCertificateType_X509, PARCContainerEncoding_DER); PARCBuffer *privateKeyBuffer; PARCCertificate *certificate = parcCertificateFactory_CreateSelfSignedCertificate(factory, &privateKeyBuffer, (char *) subjectName, keyLength, validityDays); parcCertificateFactory_Release(&factory); if (certificate != NULL) { // construct the full PKCS12 keystore to hold the certificate and private key // Extract the private key EVP_PKEY *privateKey = NULL; uint8_t *privateKeyBytes = parcBuffer_Overlay(privateKeyBuffer, parcBuffer_Limit(privateKeyBuffer)); d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &privateKeyBytes, parcBuffer_Limit(privateKeyBuffer)); parcBuffer_Release(&privateKeyBuffer); // Extract the certificate PARCBuffer *certBuffer = parcCertificate_GetDEREncodedCertificate(certificate); uint8_t *certBytes = parcBuffer_Overlay(certBuffer, parcBuffer_Limit(certBuffer)); X509 *cert = NULL; d2i_X509(&cert, (const unsigned char **) &certBytes, parcBuffer_Limit(certBuffer)); parcCertificate_Release(&certificate); PKCS12 *pkcs12 = PKCS12_create((char *) password, "ccnxuser", privateKey, cert, NULL, 0, 0, 0 /*default iter*/, PKCS12_DEFAULT_ITER /*mac_iter*/, 0); if (pkcs12 != NULL) { int fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600); if (fd != -1) { FILE *fp = fdopen(fd, "wb"); if (fp != NULL) { i2d_PKCS12_fp(fp, pkcs12); fclose(fp); result = true; } else { trapUnrecoverableState("Cannot fdopen(3) the file descriptor %d", fd); } close(fd); } else { trapUnrecoverableState("Cannot open(2) the file '%s': %s", filename, strerror(errno)); } PKCS12_free(pkcs12); X509_free(cert); EVP_PKEY_free(privateKey); } else { unsigned long errcode; while ((errcode = ERR_get_error()) != 0) { fprintf(stderr, "openssl error: %s\n", ERR_error_string(errcode, NULL)); } trapUnrecoverableState("PKCS12_create returned a NULL value."); } } return result; }