From c580a00aac271a524e5a75b35f4b91c174ed227b Mon Sep 17 00:00:00 2001 From: michele papalini Date: Thu, 23 Feb 2017 17:01:34 +0100 Subject: Initial commit: sb-forwarder, metis. Change-Id: I65ee3c851a6901929ef4417ad80d34bca0dce445 Signed-off-by: michele papalini --- metis/ccnx/forwarder/metis/core/metis_Message.h | 859 ++++++++++++++++++++++++ 1 file changed, 859 insertions(+) create mode 100644 metis/ccnx/forwarder/metis/core/metis_Message.h (limited to 'metis/ccnx/forwarder/metis/core/metis_Message.h') diff --git a/metis/ccnx/forwarder/metis/core/metis_Message.h b/metis/ccnx/forwarder/metis/core/metis_Message.h new file mode 100644 index 00000000..3b954a4e --- /dev/null +++ b/metis/ccnx/forwarder/metis/core/metis_Message.h @@ -0,0 +1,859 @@ +/* + * Copyright (c) 2017 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file metis_Message.h + * @brief MetisMessage is the unit of forwarding, i.e. the packets being switched + * + */ +#ifndef Metis_metis_Message_h +#define Metis_metis_Message_h + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +struct metis_message; +typedef struct metis_message MetisMessage; + +/** + * @function metisMessage_ReadFromBuffer + * @abstract Read bytes from the input buffer and create a MetisMessage + * @discussion + * There must be bytesToRead bytes available. + * + * @param <#param1#> + * @return <#return#> + */ +MetisMessage *metisMessage_ReadFromBuffer(unsigned ingressConnectionId, MetisTicks receiveTime, PARCEventBuffer *input, size_t bytesToRead, MetisLogger *logger); + +/** + * @function metisMessage_CreateFromBuffer + * @abstract Takes ownership of the input buffer, which comprises one complete message + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +MetisMessage *metisMessage_CreateFromBuffer(unsigned ingressConnectionId, MetisTicks receiveTime, PARCEventBuffer *input, MetisLogger *logger); + +/** + * @function metisMessage_CreateFromArray + * @abstract Copies the input buffer into the message. + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +MetisMessage *metisMessage_CreateFromArray(const uint8_t *data, size_t dataLength, unsigned ingressConnectionId, MetisTicks receiveTime, MetisLogger *logger); + +/** + * @function metisMessage_CreateFromParcBuffer + * @abstract Creates a message from the byte buffer + * @discussion + * Caller retains owership of the buffer + * + * @param <#param1#> + * @return <#return#> + */ +MetisMessage *metisMessage_CreateFromParcBuffer(PARCBuffer *buffer, unsigned ingressConnectionId, MetisTicks receiveTime, MetisLogger *logger); + +/** + * @function metisMessage_Copy + * @abstract Get a reference counted copy + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +MetisMessage *metisMessage_Acquire(const MetisMessage *message); + +/** + * Releases the message and frees the memory + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +void metisMessage_Release(MetisMessage **messagePtr); + +/** + * Writes the message to the queue + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool metisMessage_Write(PARCEventQueue *parcEventQueue, const MetisMessage *message); + +/** + * Appends the message to the buffer + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool metisMessage_Append(PARCEventBuffer *parcEventBuffer, const MetisMessage *message); + +/** + * Returns the total byte length of the message + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +size_t metisMessage_Length(const MetisMessage *message); + + +bool metisMessage_HasWldr(const MetisMessage *message); + +unsigned metisMessage_GetWldrType(const MetisMessage *message); + +unsigned metisMessage_GetWldrLabel(const MetisMessage *message); + +unsigned metisMessage_GetWldrLastReceived(const MetisMessage *message); + +void metisMessage_SetWldrLabel(MetisMessage *message, uint16_t label); + +void metisMessage_SetWldrNotification(MetisMessage *message, uint16_t expected, uint16_t lastReceived); + +/** + * Returns the connection id of the packet input + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +unsigned metisMessage_GetIngressConnectionId(const MetisMessage *message); + +/** + * Returns the receive time (in router ticks) of the message + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +MetisTicks metisMessage_GetReceiveTime(const MetisMessage *message); + +/** + * Returns the PacketType from the FixedHeader + * + * <#Paragraphs Of Explanation#> + * + * @param [in] message A parsed message + * + * @retval <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +MetisMessagePacketType metisMessage_GetType(const MetisMessage *message); + +/** + * Determines if the message has a hop limit + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @retval true A hop limit exists + * @retval false A hop limit does not exist + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool metisMessage_HasHopLimit(const MetisMessage *message); + +void metisMessage_UpdatePathLabel(MetisMessage *message, uint8_t outFace); +void metisMessage_ResetPathLabel(MetisMessage *message); + +/** + * Returns the hoplimit of the message + * + * Will assert if the message does not have a hoplimit. Use metisMessage_HasHopLimit() first + * to determine if there is a hop limit. + * + * @param [in] message An allocated MetisMessage + * + * @retval number The hop limit + * + * Example: + * @code + * { + * if (metisMessage_HasHopLimit(message)) { + * uint8_t hoplimit = metisMessage_GetHopLimit(message); + * if (hoplimit == 0) { + * // drop packet + * } else { + * metisMessage_SetHopLimit(message, hoplimit - 1); + * } + * } + * } + * @endcode + */ +uint8_t metisMessage_GetHopLimit(const MetisMessage *message); + +/** + * Sets the message hop limit to the specified value + * + * Will assert if the message does not already have a hop limit. Use metisMessage_HasHopLimit() first + * to determine if there is a hop limit. + * + * @param [in] message An allocated MetisMessage + * @param [in] hoplimit The value to set in the packet + * + * Example: + * @code + * { + * if (metisMessage_HasHopLimit(message)) { + * uint8_t hoplimit = metisMessage_GetHopLimit(message); + * if (hoplimit == 0) { + * // drop packet + * } else { + * metisMessage_SetHopLimit(message, hoplimit - 1); + * } + * } + * } + * @endcode + */ +void metisMessage_SetHopLimit(MetisMessage *message, uint8_t hoplimit); + +// =========================================================== +// Accessors used to index and compare messages + +/** + * @function metisMessage_GetName + * @abstract The name in the CCNx message + * @discussion + * The name of the Interest or Content Object. If the caller will store the + * name, he should make a reference counted copy. + * + * @param <#param1#> + * @return The name as stored in the message object. + */ +MetisTlvName *metisMessage_GetName(const MetisMessage *message); + +/** + * @function metisMessage_GetKeyIdHash + * @abstract Non-cryptographic hash of the KeyId + * @discussion + * If the message does not have a KeyId, the output pointer is left unchanged. + * + * @param hashOutput will be filled in with the hash, if a KeyId exists. + * @return true if object has a KeyId + */ +bool metisMessage_GetKeyIdHash(const MetisMessage *message, uint32_t *hashOutput); + + +/** + * Determine if the KeyIds of two Metis Messages are equal. + * + * The following equivalence relations on non-null KeyIds in `MetisMessage` instances are maintained: + * + * * It is reflexive: for any non-null reference value x, `metisMessage_KeyIdEquals(x, x)` + * must return true. + * + * * It is symmetric: for any non-null reference values x and y, + * `metisMessage_KeyIdEquals(x, y)` must return true if and only if + * `metisMessage_KeyIdEquals(y, x)` returns true. + * + * * It is transitive: for any non-null reference values x, y, and z, if + * `metisMessage_KeyIdEquals(x, y)` returns true and + * `metisMessage_KeyIdEquals(y, z)` returns true, + * then `metisMessage_KeyIdEquals(x, z)` must return true. + * + * * It is consistent: for any non-null reference values x and y, multiple + * invocations of `metisMessage_KeyIdEquals(x, y)` consistently return true or + * consistently return false. + * + * * For any non-null reference value x, `metisMessage_KeyIdEquals(x, NULL)` must + * return false. + * + * @param a A pointer to a `MetisMessage` instance. + * @param b A pointer to a `MetisMessage` instance. + * @return true if the KeyIds of the two `MetisMessage` instances are equal. + * + * Example: + * @code + * { + * MetisMessage *a = metisMessage_Create(); + * MetisMessage *b = metisMessage_Create(); + * + * if (metisMessage_KeyIdEquals(a, b)) { + * // true + * } else { + * // false + * } + * } + * @endcode + */ +bool metisMessage_KeyIdEquals(const MetisMessage *a, const MetisMessage *b); + +/** + * Determine if the ContentObjectHashes of two `Metis Messages` are equal. + * + * The ContentObjectHashes of two `MetisMessage` instances are equal if, and only if, + * a ContentObjectHash exists in both `MetisMessage` and are equal. + * + * + * The following equivalence relations on non-null KeyIds in `MetisMessage` instances are maintained: + * + * * It is reflexive: for any non-null reference value x, `metisMessage_ObjectHashEquals(x, x)` + * must return true. + * + * * It is symmetric: for any non-null reference values x and y, + * `metisMessage_ObjectHashEquals(x, y)` must return true if and only if + * `metisMessage_ObjectHashEquals(y, x)` returns true. + * + * * It is transitive: for any non-null reference values x, y, and z, if + * `metisMessage_ObjectHashEquals(x, y)` returns true and + * `metisMessage_ObjectHashEquals(y, z)` returns true, + * then `metisMessage_ObjectHashEquals(x, z)` must return true. + * + * * It is consistent: for any non-null reference values x and y, multiple + * invocations of `metisMessage_ObjectHashEquals(x, y)` consistently return true or + * consistently return false. + * + * * For any non-null reference value x, `metisMessage_ObjectHashEquals(x, NULL)` must + * return false. + * + * @param a A pointer to a `MetisMessage` instance. + * @param b A pointer to a `MetisMessage` instance. + * @return true if the KeyIds of the two `MetisMessage` instances are equal. + * + * Example: + * @code + * { + * MetisMessage *a = metisMessage_Create(); + * MetisMessage *b = metisMessage_Create(); + * + * if (metisMessage_ObjectHashEquals(a, b)) { + * // true + * } else { + * // false + * } + * } + * @endcode + */ +bool metisMessage_ObjectHashEquals(MetisMessage *a, MetisMessage *b); + +/** + * @function metisMessage_GetContentObjectHashHash + * @abstract Non-cryptographic hash of the ContentObjectHash + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return true if message has a contentobject hash and the output updated. + */ +bool metisMessage_GetContentObjectHashHash(MetisMessage *message, uint32_t *hashOutput); + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool metisMessage_HasName(const MetisMessage *message); + +/** + * Return true if there is a KeyId associated with this `MetisMessage`. * + * + * Note that this will return true if either the underlying message is an Interest that contains + * a KeyId restriction, or if the underlying message is a ContentObject that contains a KeyId. + * In the latter case, the KeyId might have been specified by the creator of the content, or + * it may have been calculated when we verified the public key specified by the ContentObject. + * + * + * @param [in] message the `MetisMessage` to query. + * + * @return true if there is a KeyId (or KeyId restriction) associated with this `MetisMessage`. + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool metisMessage_HasKeyId(const MetisMessage *message); + +/** + * Return true if there is a KeyId associated with this `MetisMessage`, and that KeyId + * has been verified. + * + * This KeyId may have been specified by the sender, or may have been calculated while + * verifying the public key associated with this `MetisMessage`s validation data, if any. + * + * @param [in] message the `MetisMessage` to query. + * + * @return true if there is a KeyId associated with this `MetisMessage`, and that KeyId has been verified. + * @return false if there is no KeyId associated with this `MetisMessage` or it has not yet been verified. + * Example: + * @code + * { + * if (metisMessage_IsKeyIdVerified(message)) { + * doSomethingWithMssage(message); + * } else { + * // KeyId was not verified + * } + * } + * @endcode + */ +bool metisMessage_IsKeyIdVerified(const MetisMessage *message); + +/** + * <#One Line Description#> + * + * <#Paragraphs Of Explanation#> + * + * @param [<#in out in,out#>] <#name#> <#description#> + * + * @return <#value#> <#explanation#> + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool metisMessage_HasContentObjectHash(const MetisMessage *message); + +/** + * @function metisMessage_GetControlMessage + * @abstract A TLV_MSG_CPI will return a control message + * @discussion + * <#Discussion#> + * + * @param <#param1#> + * @return <#return#> + */ +CCNxControl *metisMessage_CreateControlMessage(const MetisMessage *message); + +/** + * Determines if the message has an Interest Lifetime parameter + * + * <#Paragraphs Of Explanation#> + * + * @param [in] message An allocated and parsed Message + * + * @retval true If an Intrerest Lifetime field exists + * @retval false If no Interest Lifetime exists + * + * Example: + * @code + * <#example#> + * @endcode + */ +bool metisMessage_HasInterestLifetime(const MetisMessage *message); + +/** + * Returns the Interest lifetime + * + * Will trap if the message does not contain an Interest lifetime + * + * @param [in] message An allocated and parsed Message + * + * @retval integer Lifetime in forwarder Ticks + * + * Example: + * @code + * <#example#> + * @endcode + */ +uint64_t metisMessage_GetInterestLifetimeTicks(const MetisMessage *message); + +/** + * Return true if the specified `MetisMessage` instance contains a RecommendedCacheTime. + * + * The Recommended Cache Time (a millisecond timestamp) is a network byte ordered unsigned integer of the number of + * milliseconds since the epoch in UTC of when the payload expires. It is a 64-bit field. + * + * @param message the `MetisMessage` instance to check for RecommendedCacheTime. + * @return true if the specified `MetisMessage` instance has a RecommendedCacheTime. + * @return false otherwise. + * Example: + * @code + * { + * MetisMessage *metisMessage = <...>; + * if (metisMessage_HasRecommendedCacheTime(metisMessage)) { + * uint64_t rct = metisMessage_GetRecommendedCacheTimeTicks(metisMessage); + * } + * } + * @endcode + * @see metisMessage_GetRecommendedCacheTimeTicks + */ +bool metisMessage_HasRecommendedCacheTime(const MetisMessage *message); + +/** + * Return the RecommendedCacheTime of the specified `MetisMessage`, if available, in Metis ticks. If not, it will trap. + * Before calling this function, call {@link metisMessage_HasRecommendedCacheTime} first. + * + * The Recommended Cache Time (a millisecond timestamp) is a network byte ordered unsigned integer of the number of + * milliseconds since the epoch in UTC of when the payload expires. It is a 64-bit field. + * + * The Recommended Cache Time is initially set from the referenced tlv_skeleton, but may be assigned by calling + * {@link metisMessage_SetRecommendedCacheTimeTicks}. + * + * @param message the `MetisMessage` instance to check for RecommendedCacheTime. + * @return the RecommendedCacheTime of the specified `MetisMessage`. + * + * Example: + * @code + * { + * MetisMessage *metisMessage = <...>; + * if (metisMessage_HasRecommendedCacheTime(metisMessage)) { + * uint64_t rct = metisMessage_GetRecommendedCacheTimeTicks(metisMessage); + * } + * } + * @endcode + * + * @see metisMessage_HasRecommendedCacheTime + * @see metisMessage_SetRecommendedCacheTimeTicks + */ +uint64_t metisMessage_GetRecommendedCacheTimeTicks(const MetisMessage *message); + +/** + * Return true if the specified `MetisMessage` instance contains an ExpiryTime. + * + * The ExpiryTime is the time at which the Payload expires, as expressed by a timestamp containing the number of milliseconds + * since the epoch in UTC. It is a network byte order unsigned integer in a 64-bit field. A cache or end system should not + * respond with a Content Object past its ExpiryTime. Routers forwarding a Content Object do not need to check the ExpiryTime. + * If the ExpiryTime field is missing, the Content Object has no expressed expiration and a cache or end system may use the + * Content Object for as long as desired. + * + * @param message the `MetisMessage` instance to check for ExpiryTime. + * @return true if the specified `MetisMessage` instance has an ExpiryTime. + * @return false otherwise. + * + * Example: + * @code + * { + * MetisMessage *metisMessage = <...>; + * if (metisMessage_HasExpiryTime(metisMessage)) { + * uint64_t expiryTime = metisMessage_GetExpiryTimeTicks(metisMessage); + * } + * } + * @endcode + * + * @see metisMessage_GetExpiryTimeTicks + * @see metisMessage_SetExpiryTimeTicks + */ +bool metisMessage_HasExpiryTime(const MetisMessage *message); + +/** + * Return the ExpiryTime of the specified `MetisMessage`, if available, in Metis ticks. If not, it will trap. + * Before calling this function, call {@link metisMessage_HasExpiryTime} first. + * + * The ExpiryTime is the time at which the Payload expires, as expressed by a timestamp containing the number of milliseconds + * since the epoch in UTC. It is a network byte order unsigned integer in a 64-bit field. A cache or end system should not + * respond with a Content Object past its ExpiryTime. Routers forwarding a Content Object do not need to check the ExpiryTime. + * If the ExpiryTime field is missing, the Content Object has no expressed expiration and a cache or end system may use the + * Content Object for as long as desired. + * + * The ExpiryTime is initially set from the referenced tlv_skeleton, but may be assigned by calling + * {@link metisMessage_SetExpiryTimeTicks}. + * + * @param message the `MetisMessage` instance to check for ExpiryTime. + * @return the ExpiryTime of the specified `MetisMessage`. + * + * Example: + * @code + * { + * MetisMessage *metisMessage = <...>; + * if (metisMessage_HasExpiryTime(metisMessage)) { + * uint64_t rct = metisMessage_GetExpiryTimeTicks(metisMessage); + * } + * } + * @endcode + * + * @see metisMessage_HasExpiryTime + * @see metisMessage_SetExpiryTimeTicks + */ +uint64_t metisMessage_GetExpiryTimeTicks(const MetisMessage *message); + +/** + * Assign the ExpiryTime of the specified `MetisMessage`, in Metis ticks. This will not update the + * referenced tlv_skeleton. + * + * The ExpiryTime is the time at which the Payload expires, as expressed by a timestamp containing the number of milliseconds + * since the epoch in UTC. It is a network byte order unsigned integer in a 64-bit field. A cache or end system should not + * respond with a Content Object past its ExpiryTime. Routers forwarding a Content Object do not need to check the ExpiryTime. + * If the ExpiryTime field is missing, the Content Object has no expressed expiration and a cache or end system may use the + * Content Object for as long as desired. + * + * @param message the `MetisMessage` instance to check for ExpiryTime. + * @param expiryTimeTicks the time, in ticks, that this message's payload will expire. + * + * Example: + * @code + * { + * MetisMessage *metisMessage = <...>; + * uint64_t timeInTicks = <...>; + * metisMessage_SetExpiryTimeTicks(metisMessage, timeInTicks); + * } + * @endcode + * + * @see metisMessage_HasExpiryTime + * @see metisMessage_GetExpiryTimeTicks + */ +void metisMessage_SetExpiryTimeTicks(MetisMessage *message, uint64_t expiryTimeTicks); + +/** + * Assign the RecommendedCacheTime of the specified `MetisMessage`, in Metis ticks. This will not update the + * referenced tlv_skeleton. + * + * The Recommended Cache Time (a millisecond timestamp) is a network byte ordered unsigned integer of the number of + * milliseconds since the epoch in UTC of when the payload expires. It is a 64-bit field. + * + * @param message the `MetisMessage` instance to check for ExpiryTime. + * @param expiryTimeTicks the time, in ticks, that this message's payload will expire. + * + * Example: + * @code + * { + * MetisMessage *metisMessage = <...>; + * uint64_t timeInTicks = <...>; + * metisMessage_SetRecommendedCacheTimeTicks(metisMessage, timeInTicks); + * } + * @endcode + * + * @see metisMessage_HasExpiryTime + */ +void metisMessage_SetRecommendedCacheTimeTicks(MetisMessage *message, uint64_t recommendedCacheTimeTicks); + +/** + * Return true if there is a public key associated with the specified `MetisMessage`. + * + * @param message the `MetisMessage` instance to check for a public key. + * + * @return true if there is a public key in this `MetisMessage`. + * @return false otherwise. + */ +bool metisMessage_HasPublicKey(const MetisMessage *message); + +/** + * Return true if there is a certificate associated with the specified `MetisMessage`. + * + * @param message the `MetisMessage` instance to check for certificate. + * + * @return true if there is a certificate in this `MetisMessage`. + * @return false otherwise. + */ +bool metisMessage_HasCertificate(const MetisMessage *message); + +/** + * Return the public key associated with the specified `MetisMessage`, if it exists. + * + * @param message the `MetisMessage` instance to check for a public key. + * + * @return a pointer to a PARCBuffer containing the public key of this `MetisMessage`. + * @return NULL if no public key exists. + */ +PARCBuffer *metisMessage_GetPublicKey(const MetisMessage *message); + +/** + * Return the certificate associated with the specified `MetisMessage`, if it exists. + * + * @param message the `MetisMessage` instance to check for a certificate. + * + * @return a pointer to a PARCBuffer containing the certificate of this `MetisMessage`. + * @return NULL if no certificate exists. + */ +PARCBuffer *metisMessage_GetCertificate(const MetisMessage *message); + +/** + * Tests if the packet has a fragment payload + * + * The fragment payload is part of a larger packet + * + * @param [in] message An allocated and parsed Message + * + * @return true The packet contains a portion of another packet + * @return false There is no fragment payload + * + * Example: + * @code + * { + * <#example#> + * } + * @endcode + */ +bool metisMessage_HasFragmentPayload(const MetisMessage *message); + +/** + * Appends the fragment payload to the given buffer + * + * Will append the fragment payload from the message to the given buffer. + * This is a non-destructive copy. If there is no fragment payload in the + * message, 0 bytes will be copied and 0 returned. + * + * @param [in] message An allocated and parsed Message + * @param [in] buffer The buffer to append to + * + * @return number The number of bytes appended + * + * Example: + * @code + * { + * <#example#> + * } + * @endcode + */ +size_t metisMessage_AppendFragmentPayload(const MetisMessage *message, PARCEventBuffer *buffer); + +/** + * Returns a pointer to the beginning of the FixedHeader + * + * <#Paragraphs Of Explanation#> + * + * @param [in] message An allocated and parsed Message + * + * @return non-null The fixed header memory + * @return null No fixed header or an error + * + * Example: + * @code + * { + * <#example#> + * } + * @endcode + */ +const uint8_t *metisMessage_FixedHeader(const MetisMessage *message); + +/** + * Creates a new MetisMessage from a slice of a first message + * + * The new MetisMessage will be the header byte array prefix followed by the slice extent. + * The resulting MetisMessage must be freed by calling metisMessage_Release(). + * + * Depending on the implementation, this may make a reference to the first message and access the + * memory by reference. + * + * The offset + length must be less than or equal to metisMessage_Length(). It is an error + * to call with a 0 length. + * + * @param [in] message The original message to slice + * @param [in] offset The offset within the message to start the slice + * @param [in] length The length after the offset to include in the slice (must be positive) + * @param [in] headerLength The length of the header to prepend (may be 0) + * @param [in] header The header to prepend (may be NULL with 0 length) + * + * @return non-null A new MetisMessage that has the header plus slice + * @return null An error + * + * Example: + * @code + * { + * uint8_t interestToFragment[] = { + * 0x01, 0x00, 0x00, 24, // ver = 1, type = interest, length = 24 + * 0x20, 0x00, 0x11, 8, // HopLimit = 32, reserved = 0, flags = 0x11, header length = 8 + * 0x00, 0x01, 0x00, 12, // type = interest, length = 12 + * 0x00, 0x00, 0x00, 8, // type = name, length = 8 + * 0x00, 0x02, 0x00, 4, // type = binary, length = 4 + * 'c', 'o', 'o', 'l', // "cool" + * }; + * + * MetisMessage *firstMessage = metisMessage_CreateFromArray(interestToFragment, sizeof(interestToFragment), 1, 100, logger); + * + * uint8_t fragmentHeader[] = { + * 0x01, 0x05, 0x00, 12, // hop-by-hop fragment + * 0x40, 0x00, 0x01, 8, // B flag, seqnum = 1 + * 0x00, 0x05, 0x00, 8, // fragment data, length = 8 + * }; + * + * MetisMessage *secondMessage = metisMessage_Slice(firstMessage, 0, 8, sizeof(fragmentHeader), fragmentHeader,); + * // the secondMessage message contains the fragmentHeader followed by the first 8 bytes + * // of the first message, as showin in wireFormat below. + * + * uint8_t wireFormat[] = { + * 0x01, 0x05, 0x00, 12, // hop-by-hop fragment + * 0x40, 0x00, 0x01, 8, // B flag, seqnum = 1 + * 0x00, 0x05, 0x00, 8, // fragment data, length = 8 + * 0x01, 0x00, 0x00, 24, // ver = 1, type = interest, length = 24 + * 0x20, 0x00, 0x11, 8, // HopLimit = 32, reserved = 0, flags = 0x11, header length = 8 + * }; + * + * metisMessage_Release(&firstMessage); + * metisMessage_Release(&secondMessage); + * } + * @endcode + */ +MetisMessage *metisMessage_Slice(const MetisMessage *message, size_t offset, size_t length, size_t headerLength, const uint8_t header[headerLength]); +#endif // Metis_metis_Message_h -- cgit 1.2.3-korg