LONGBOW_TEST_CASE(Object, parcRandomAccessFile_Read) { char *fname = "tmpfile"; PARCFile *file = parcFile_Create(fname); parcFile_CreateNewFile(file); FILE *fp = fopen(fname, "w"); fseek(fp, 0, SEEK_SET); uint8_t data[128]; for (int i = 0; i < 128; i++) { data[i] = i; } fwrite(data, 1, 128, fp); fclose(fp); PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file); parcFile_Release(&file); PARCBuffer *buffer = parcBuffer_Allocate(128); size_t numBytes = parcRandomAccessFile_Read(instance, buffer); assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes); parcBuffer_Flip(buffer); uint8_t *bytes = parcBuffer_Overlay(buffer, parcBuffer_Remaining(buffer)); assertTrue(memcmp(data, bytes, 128) == 0, "Expected buffers to be equal"); parcBuffer_Release(&buffer); parcRandomAccessFile_Close(instance); parcRandomAccessFile_Release(&instance); }
LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_Buffer) { PARCBuffer *buffer = parcBuffer_Allocate(1024); for (size_t i = 0; i < 32; i++) { for (size_t j = 0; j < 32; j++) { parcBuffer_PutUint8(buffer, i); } } parcBuffer_Flip(buffer); PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes assertNotNull(chunker, "Expected non-NULL Chunker"); PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker); size_t count = 0; while (parcIterator_HasNext(itr)) { PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr); uint8_t *contents = parcBuffer_Overlay(payload, 0); for (size_t i = 0; i < 32; i++) { assertTrue(contents[i] == (31 - count), "Expected %zu at index %zu, got %d", (31 - count), i, contents[i]); } count++; parcBuffer_Release(&payload); } assertTrue(count == 32, "Expected to iterate over 32 content objects from the chunker, but for %zu", count); parcIterator_Release(&itr); parcBufferChunker_Release(&chunker); parcBuffer_Release(&buffer); }
LONGBOW_TEST_CASE(Global, parc_Chunker_ReverseIterator_BufferSmall) { PARCBuffer *buffer = parcBuffer_Allocate(16); // Special 0xFF to mark the start for (int i = 0; i < 16; i++) { parcBuffer_PutUint8(buffer, 0xFF); } parcBuffer_Flip(buffer); PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes assertNotNull(chunker, "Expected non-NULL Chunker"); PARCIterator *itr = parcBufferChunker_ReverseIterator(chunker); size_t count = 0; while (parcIterator_HasNext(itr)) { PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr); uint8_t *contents = parcBuffer_Overlay(payload, 0); for (size_t i = 0; i < 16; i++) { assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]); } count++; parcBuffer_Release(&payload); } assertTrue(count == 1, "Expected to iterate over 1 content objects from the chunker, but for %zu", count); parcIterator_Release(&itr); parcBufferChunker_Release(&chunker); parcBuffer_Release(&buffer); }
LONGBOW_TEST_CASE(JSON, parcJSON_AddValue) { PARCJSON *json = parcJSON_Create(); char *expectedName = "value"; PARCJSONValue *value = parcJSONValue_CreateFromCString("Some Pig"); parcJSON_AddValue(json, expectedName, value); const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName); PARCBuffer *actualName = parcJSONPair_GetName(pair); PARCJSONValue *actualValue = parcJSONPair_GetValue(pair); assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0, "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName)); assertTrue(parcJSONValue_IsString(actualValue), "Expect value to be type PARCJSONArray"); assertTrue(parcBuffer_Equals(parcJSONValue_GetString(actualValue), parcJSONValue_GetString(value)), "Expected %s actual %s", parcJSONValue_ToString(value), parcJSONValue_ToString(actualValue)); parcJSONValue_Release(&value); parcJSON_Release(&json); }
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; }
static PARCSignature * _SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign) { parcSecurity_AssertIsInitialized(); assertNotNull(signer, "Parameter must be non-null CCNxFileKeystore"); assertNotNull(digestToSign, "Buffer to sign must not be null"); // TODO: what is the best way to expose this? PARCKeyStore *keyStore = signer->keyStore; PARCBuffer *privateKeyBuffer = parcKeyStore_GetDEREncodedPrivateKey(keyStore); EVP_PKEY *privateKey = NULL; size_t keySize = parcBuffer_Remaining(privateKeyBuffer); uint8_t *bytes = parcBuffer_Overlay(privateKeyBuffer, keySize); privateKey = d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &bytes, keySize); parcBuffer_Release(&privateKeyBuffer); RSA *rsa = EVP_PKEY_get1_RSA(privateKey); int opensslDigestType; switch (parcCryptoHash_GetDigestType(digestToSign)) { case PARCCryptoHashType_SHA256: opensslDigestType = NID_sha256; break; case PARCCryptoHashType_SHA512: opensslDigestType = NID_sha512; break; default: trapUnexpectedState("Unknown digest type: %s", parcCryptoHashType_ToString(parcCryptoHash_GetDigestType(digestToSign))); } uint8_t *sig = parcMemory_Allocate(RSA_size(rsa)); assertNotNull(sig, "parcMemory_Allocate(%u) returned NULL", RSA_size(rsa)); unsigned sigLength = 0; PARCBuffer *bb_digest = parcCryptoHash_GetDigest(digestToSign); int result = RSA_sign(opensslDigestType, (unsigned char *) parcByteArray_Array(parcBuffer_Array(bb_digest)), (int) parcBuffer_Remaining(bb_digest), sig, &sigLength, rsa); assertTrue(result == 1, "Got error from RSA_sign: %d", result); RSA_free(rsa); PARCBuffer *bbSign = parcBuffer_Allocate(sigLength); parcBuffer_Flip(parcBuffer_PutArray(bbSign, sigLength, sig)); parcMemory_Deallocate((void **) &sig); PARCSignature *signature = parcSignature_Create(_GetSigningAlgorithm(signer), parcCryptoHash_GetDigestType(digestToSign), bbSign ); parcBuffer_Release(&bbSign); return signature; }
// // Peek at the header and derive our total message length // static size_t _messageLengthFromHeader(AthenaTransportLink *athenaTransportLink, _UDPLinkData *linkData) { // Peek at our message header to determine the total length of buffer we need to allocate. size_t fixedHeaderLength = ccnxCodecTlvPacket_MinimalHeaderLength(); PARCBuffer *wireFormatBuffer = parcBuffer_Allocate(fixedHeaderLength); const uint8_t *peekBuffer = parcBuffer_Overlay(wireFormatBuffer, 0); ssize_t readCount = recv(linkData->fd, (void *) peekBuffer, fixedHeaderLength, MSG_PEEK); if (readCount == -1) { parcBuffer_Release(&wireFormatBuffer); if ((errno == EAGAIN) || (errno == EINTR)) { parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "recv retry (%s)", strerror(errno)); linkData->_stats.receive_ReadRetry++; } else { linkData->_stats.receive_ReadError++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "recv error (%s)", strerror(errno)); athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Error); } return -1; } // A zero read means no data if (readCount == 0) { parcBuffer_Release(&wireFormatBuffer); return -1; } // Check for a short header read, since we're only peeking here we just return and retry later if (readCount != fixedHeaderLength) { linkData->_stats.receive_ReadHeaderFailure++; parcBuffer_Release(&wireFormatBuffer); return -1; } // Obtain the total size of the message from the header size_t messageLength = ccnxCodecTlvPacket_GetPacketLength(wireFormatBuffer); parcBuffer_Release(&wireFormatBuffer); // Could do more to check the integrity of the message and framing. // If length is greater than our MTU we will find out in the read. if (messageLength < fixedHeaderLength) { linkData->_stats.receive_BadMessageLength++; parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "Framing error, flushing link."); char trash[MAXPATHLEN]; // Flush link to attempt to resync our framing while (read(linkData->fd, trash, sizeof(trash)) == sizeof(trash)) { parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "... flushing link."); } return -1; } return messageLength; }
PARCHashCode parcBuffer_HashCode(const PARCBuffer *buffer) { PARCHashCode result = 0; size_t remaining = parcBuffer_Remaining(buffer); if (remaining > 0) { result = parcHashCode_Hash(parcBuffer_Overlay((PARCBuffer *) buffer, 0), parcBuffer_Remaining(buffer)); } 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; }
int parcBuffer_Compare(const PARCBuffer *x, const PARCBuffer *y) { if (x == y) { return 0; } if (x == NULL) { return -1; } if (y == NULL) { return +1; } size_t count = parcBuffer_Remaining(x); if (count > parcBuffer_Remaining(y)) { count = parcBuffer_Remaining(y); } int result = 0; if (count > 0) { result = memcmp(parcBuffer_Overlay((PARCBuffer *) x, 0), parcBuffer_Overlay((PARCBuffer *) y, 0), count); } if (result == 0) { // This is when one buffer is longer than the other, and they are equivalent thus far. ssize_t difference = parcBuffer_Remaining(x) - parcBuffer_Remaining(y); if (difference > 0) { result = +1; } else if (difference < 0) { result = -1; } } return result; }
CCNxPortalAnchor * ccnxPortalAnchor_CreateFromJSON(const PARCJSON *json) { CCNxPortalAnchor *result = parcObject_CreateInstance(CCNxPortalAnchor); if (result != NULL) { result->prefix = ccnxName_CreateFromURI(parcBuffer_Overlay(parcJSONValue_GetString(parcJSON_GetByPath(json, "/namePrefix")), 0)); result->expireTime = parcJSONValue_GetInteger(parcJSON_GetByPath(json, "/expireTime")); ccnxPortalAnchor_OptionalAssertValid(result); } return result; }
/** * If successful, return true and fill in the parameters in the output argument */ bool publicKeySignerPkcs12Store_GetConnectionParams(PARCJSON *connectionJson, struct publickeysigner_params *output) { assertNotNull(connectionJson, "Parameter connectionJson must be non-null"); assertNotNull(output, "Parameter output must be non-null"); PARCJSONValue *value = parcJSON_GetValueByName(connectionJson, publicKeySignerPkcs12Store_GetName()); assertNotNull(value, "JSON key %s missing", publicKeySignerPkcs12Store_GetName()); PARCJSON *keystoreJson = parcJSONValue_GetJSON(value); value = parcJSON_GetValueByName(keystoreJson, param_KEYSTORE_NAME); assertNotNull(value, "JSON key %s missing inside %s", param_KEYSTORE_NAME, publicKeySignerPkcs12Store_GetName()); PARCBuffer *sBuf = parcJSONValue_GetString(value); output->filename = parcBuffer_Overlay(sBuf, 0); value = parcJSON_GetValueByName(keystoreJson, param_KEYSTORE_PASSWD); assertNotNull(value, "JSON key %s missing inside %s", param_KEYSTORE_PASSWD, publicKeySignerPkcs12Store_GetName()); sBuf = parcJSONValue_GetString(value); output->password = parcBuffer_Overlay(sBuf, 0); return true; }
// // 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; }
char * parcBuffer_ToString(const PARCBuffer *buffer) { size_t remaining = parcBuffer_Remaining(buffer); char *result = parcMemory_Allocate(remaining + 1); if (remaining > 0) { assertNotNull(result, "parcMemory_Allocate returned NULL"); if (result != NULL) { memcpy(result, parcBuffer_Overlay((PARCBuffer *) buffer, 0), remaining); } } result[remaining] = 0; return result; }
LONGBOW_TEST_CASE(JSON, parcJSON_AddString) { PARCJSON *json = parcJSON_Create(); char *expectedName = "string"; char *expectedValue = "value"; parcJSON_AddString(json, expectedName, expectedValue); const PARCJSONPair *pair = parcJSON_GetPairByName(json, "string"); PARCBuffer *actualName = parcJSONPair_GetName(pair); PARCJSONValue *actualValue = parcJSONPair_GetValue(pair); assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0, "Expected name %s, actual %s", expectedName, parcBuffer_ToString(actualName)); assertTrue(strcmp(expectedValue, parcBuffer_Overlay(parcJSONValue_GetString(actualValue), 0)) == 0, "Expected value %s, actual %s", expectedValue, parcJSONValue_ToString(actualValue)); parcJSON_Release(&json); }
uint64_t parcBuffer_ParseNumeric(PARCBuffer *buffer) { uint64_t result = 0; char *bytes = parcBuffer_Overlay(buffer, 0); if (parcBuffer_Remaining(buffer) > 2 && bytes[0] == '0' && bytes[1] == 'x') { result = parcBuffer_ParseHexNumber(buffer); } else { result = parcBuffer_ParseDecimalNumber(buffer); } return result; }
LONGBOW_TEST_CASE(parcURISegment, parcURISegment_GetBuffer) { const char *pointer; PARCURISegment *segment = parcURISegment_Parse(URI_PATH_SEGMENT, &pointer); assertNotNull(segment, "Expected non-null result."); assertTrue(*pointer == 0, "Expected pointer to point to the null terminating byte."); PARCBuffer *buffer = parcURISegment_GetBuffer(segment); char *expected = URI_PATH_SEGMENT; char *actual = (char *) parcBuffer_Overlay(buffer, 0); size_t compareLength = strlen(URI_PATH_SEGMENT); assertTrue(strncmp(expected, actual, compareLength), "Buffer does not contain original data."); parcURISegment_Release(&segment); }
LONGBOW_TEST_CASE(Global, parc_Chunker_ForwardIterator_BufferPartial) { // Allocate something that's not divisible by the chunk size PARCBuffer *buffer = parcBuffer_Allocate(1030); for (size_t i = 0; i < 32; i++) { for (size_t j = 0; j < 32; j++) { parcBuffer_PutUint8(buffer, i); } } // Special 0xFF to mark the end... for (int i = 0; i < 6; i++) { parcBuffer_PutUint8(buffer, 0xFF); } parcBuffer_Flip(buffer); PARCBufferChunker *chunker = parcBufferChunker_Create(buffer, 32); // each chunk is 32 bytes assertNotNull(chunker, "Expected non-NULL Chunker"); PARCIterator *itr = parcBufferChunker_ForwardIterator(chunker); size_t count = 0; while (parcIterator_HasNext(itr)) { PARCBuffer *payload = (PARCBuffer *) parcIterator_Next(itr); uint8_t *contents = parcBuffer_Overlay(payload, 0); if (count < 32) { for (size_t i = 0; i < 32; i++) { assertTrue(contents[i] == count, "Expected %zu at index %zu, got %d", count, i, contents[i]); } } else { for (size_t i = 0; i < 6; i++) { assertTrue(contents[i] == 0xFF, "Expected %zu at index %zu, got %d", (size_t) 0xFF, i, contents[i]); } } count++; parcBuffer_Release(&payload); } assertTrue(count == 33, "Expected to iterate over 33 content objects from the chunker, but for %zu", count); parcIterator_Release(&itr); parcBufferChunker_Release(&chunker); parcBuffer_Release(&buffer); }
MetisTlvName * metisTlvName_CreateFromCCNxName(const CCNxName *ccnxName) { // to avoid reallocs, calculate the exact size we need size_t memoryLength = 0; for (size_t i = 0; i < ccnxName_GetSegmentCount(ccnxName); i++) { CCNxNameSegment *segment = ccnxName_GetSegment(ccnxName, i); memoryLength += 4 + ccnxNameSegment_Length(segment); } MetisTlvName *name = parcMemory_AllocateAndClear(sizeof(MetisTlvName)); assertNotNull(name, "parcMemory_AllocateAndClear(%zu) returned NULL", sizeof(MetisTlvName)); name->memoryLength = memoryLength; name->memory = parcMemory_Allocate(memoryLength); assertNotNull(name->memory, "parcMemory_Allocate(%zu) returned NULL", memoryLength); uint8_t *p = name->memory; uint8_t *end = p + memoryLength; for (size_t i = 0; i < ccnxName_GetSegmentCount(ccnxName); i++) { CCNxNameSegment *segment = ccnxName_GetSegment(ccnxName, i); uint16_t type = ccnxNameSegment_GetType(segment); uint16_t length = ccnxNameSegment_Length(segment); *(uint16_t *) p = htons(type); p += 2; *(uint16_t *) p = htons(length); p += 2; if (length >0) { PARCBuffer *buffer = ccnxNameSegment_GetValue(segment); uint8_t *overlay = parcBuffer_Overlay(buffer, 0); memcpy(p, overlay, length); p += length; } // sanity check assertTrue(p <= end, "Wrote past the end of buffer, now at %p end at %p", p, end); } _setup(name); return name; }
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; }
LONGBOW_TEST_CASE(Global, parcNetwork_LinkAddress_BuildString_colons) { char *expected = "link://01-23-45-67-89-ab"; PARCBuffer *address = parcNetwork_ParseLinkAddress("link://01:23:45:67:89:ab"); PARCBufferComposer *composer = parcBufferComposer_Create(); parcNetwork_LinkAddress_BuildString((unsigned char *) parcBuffer_Overlay(address, 0), parcBuffer_Remaining(address), composer); PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); char *actual = parcBuffer_ToString(tempBuffer); parcBuffer_Release(&tempBuffer); assertTrue(strcmp(expected, actual) == 0, "Expected '%s', actual '%s'", expected, actual); parcMemory_Deallocate((void **) &actual); parcBufferComposer_Release(&composer); parcBuffer_Release(&address); }
size_t tutorialFileIO_AppendFileChunk(const char *fileName, const PARCBuffer *chunk) { size_t numBytesWritten = 0; FILE *file = fopen(fileName, "a"); // Open for appending. Create if it doesn't exist. assertNotNull(file, "Could not open file '%s' - stopping.", fileName); const void *buffer = parcBuffer_Overlay((PARCBuffer *) chunk, 0); // We're un-const'ing for parcBuffer_Overlay, but we do not change the buffer state. numBytesWritten = fwrite(buffer, 1, parcBuffer_Remaining(chunk), file); assertTrue(numBytesWritten == parcBuffer_Remaining(chunk), "Couldn't write requested chunk to file: %s", fileName); fclose(file); return numBytesWritten; }
int ccnGet(PARCIdentity *identity, CCNxName *name) { CCNxPortalFactory *factory = ccnxPortalFactory_Create(identity); CCNxPortal *portal = ccnxPortalFactory_CreatePortal(factory, ccnxPortalRTA_Message); assertNotNull(portal, "Expected a non-null CCNxPortal pointer."); CCNxInterest *interest = ccnxInterest_CreateSimple(name); ccnxName_Release(&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_IsContentObject(response)) { CCNxContentObject *contentObject = ccnxMetaMessage_GetContentObject(response); PARCBuffer *payload = ccnxContentObject_GetPayload(contentObject); size_t length = parcBuffer_Remaining(payload); ssize_t nwritten = write(1, parcBuffer_Overlay(payload, length), length); assertTrue(nwritten == length, "Did not write whole buffer, got %zd expected %zu", nwritten, length); break; } ccnxMetaMessage_Release(&response); } } } ccnxPortal_Release(&portal); ccnxPortalFactory_Release(&factory); return 0; }
LONGBOW_TEST_CASE(JSON, parcJSON_AddInteger) { PARCJSON *json = parcJSON_Create(); char *expectedName = "integer"; uint64_t expectedValue = 12345; parcJSON_AddInteger(json, expectedName, expectedValue); const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName); PARCBuffer *actualName = parcJSONPair_GetName(pair); PARCJSONValue *actualValue = parcJSONPair_GetValue(pair); assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0, "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName)); assertTrue(expectedValue == parcJSONValue_GetInteger(actualValue), "Expected %" PRIi64 "d actual %" PRIi64 "d", expectedValue, parcJSONValue_GetInteger(actualValue)); parcJSON_Release(&json); }
LONGBOW_TEST_CASE(JSON, parcJSON_AddBoolean) { PARCJSON *json = parcJSON_Create(); char *expectedName = "boolean"; bool expectedValue = true; parcJSON_AddBoolean(json, expectedName, expectedValue); const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName); PARCBuffer *actualName = parcJSONPair_GetName(pair); PARCJSONValue *actualValue = parcJSONPair_GetValue(pair); assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0, "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName)); assertTrue(expectedValue == parcJSONValue_GetBoolean(actualValue), "Expected %d actual %d", expectedValue, parcJSONValue_GetBoolean(actualValue)); parcJSON_Release(&json); }
LONGBOW_TEST_CASE(JSON, parcJSON_AddObject) { PARCJSON *json = parcJSON_Create(); PARCJSON *expectedValue = parcJSON_ParseString("{ \"string\" : \"xyzzy\" }"); parcJSON_AddObject(json, "object", expectedValue); char *expectedName = "object"; const PARCJSONPair *pair = parcJSON_GetPairByName(json, expectedName); PARCBuffer *actualName = parcJSONPair_GetName(pair); PARCJSONValue *actualValue = parcJSONPair_GetValue(pair); assertTrue(strcmp(expectedName, parcBuffer_Overlay(actualName, 0)) == 0, "Expected name %s, actual %s", expectedName, (char *) parcBuffer_ToString(actualName)); assertTrue(parcJSON_Equals(expectedValue, parcJSONValue_GetJSON(actualValue)), "Expected value did not match the actual value."); parcJSON_Release(&expectedValue); parcJSON_Release(&json); }
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; }
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; }