diff options
Diffstat (limited to 'libccnx-portal/ccnx/api/ccnx_Portal/ccnx_Portal.c')
-rwxr-xr-x | libccnx-portal/ccnx/api/ccnx_Portal/ccnx_Portal.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/libccnx-portal/ccnx/api/ccnx_Portal/ccnx_Portal.c b/libccnx-portal/ccnx/api/ccnx_Portal/ccnx_Portal.c new file mode 100755 index 00000000..94e36086 --- /dev/null +++ b/libccnx-portal/ccnx/api/ccnx_Portal/ccnx_Portal.c @@ -0,0 +1,257 @@ +/* + * 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. + */ + +/** + */ +#include <config.h> + +#include <pthread.h> + +#include <LongBow/runtime.h> + +#include <ccnx/api/ccnx_Portal/ccnx_Portal.h> +#include <ccnx/api/ccnx_Portal/ccnx_PortalAnchor.h> + +#include <parc/algol/parc_Object.h> +#include <parc/algol/parc_DisplayIndented.h> +#include <ccnx/api/control/controlPlaneInterface.h> + +#include <ccnx/transport/common/transport.h> + +struct ccnx_portal_status { + int error; + bool eof; +}; + +struct ccnx_portal { + CCNxPortalStatus status; + + const CCNxPortalStack *stack; +}; + +static CCNxMetaMessage * +_ccnxPortal_ComposeAnchorMessage(const CCNxName *routerName, const CCNxName *name, int secondsToLive) +{ + time_t expireTime = time(0) + secondsToLive; + CCNxPortalAnchor *namePrefix = ccnxPortalAnchor_Create(name, expireTime); + + PARCBufferComposer *composer = parcBufferComposer_Create(); + ccnxPortalAnchor_Serialize(namePrefix, composer); + PARCBuffer *payload = parcBufferComposer_ProduceBuffer(composer); + + CCNxInterest *interest = ccnxInterest_CreateSimple(routerName); + ccnxInterest_SetPayload(interest, payload); + + CCNxMetaMessage *message = ccnxMetaMessage_CreateFromInterest(interest); + + parcBuffer_Release(&payload); + ccnxInterest_Release(&interest); + parcBufferComposer_Release(&composer); + ccnxPortalAnchor_Release(&namePrefix); + + return message; +} + +static int +_ccnxPortal_SetAnchor(CCNxPortal *portal, const CCNxName *name, time_t secondsToLive) +{ + int64_t timeOutMicroSeconds = parcProperties_GetAsInteger(ccnxPortalStack_GetProperties(portal->stack), CCNxPortalFactory_LocalRouterTimeout, 1000000); + + CCNxName *routerName = ccnxName_CreateFromCString(ccnxPortalStack_GetProperty(portal->stack, CCNxPortalFactory_LocalRouterName, "lci:/local/dcr")); + CCNxName *fullName = ccnxName_ComposeNAME(routerName, "anchor"); + + CCNxMetaMessage *message = _ccnxPortal_ComposeAnchorMessage(fullName, name, secondsToLive); + + ccnxPortal_Send(portal, message, CCNxStackTimeout_MicroSeconds(timeOutMicroSeconds)); + ccnxMetaMessage_Release(&message); + + CCNxMetaMessage *response = ccnxPortal_Receive(portal, CCNxStackTimeout_MicroSeconds(timeOutMicroSeconds)); + if (response != NULL) { + ccnxMetaMessage_Release(&response); + } + + ccnxName_Release(&fullName); + ccnxName_Release(&routerName); + + return 0; +} + +bool +ccnxPortal_Flush(CCNxPortal *portal, const CCNxStackTimeout *timeout) +{ + CCNxControl *control = ccnxControl_CreateFlushRequest(); + + // this needs to be better wrapped in ccnxControl + PARCJSON *json = ccnxControl_GetJson(control); + uint64_t expectedSequenceNumber = controlPlaneInterface_GetSequenceNumber(json); + + CCNxMetaMessage *message = ccnxMetaMessage_CreateFromControl(control); + bool result = ccnxPortal_Send(portal, message, CCNxStackTimeout_Never); + + ccnxMetaMessage_Release(&message); + ccnxControl_Release(&control); + + if (result == true) { + bool matchedSequenceNumber = false; + while (!matchedSequenceNumber) { + message = ccnxPortal_Receive(portal, CCNxStackTimeout_Never); + if (message) { + if (ccnxMetaMessage_IsControl(message)) { + control = ccnxMetaMessage_GetControl(message); + if (ccnxControl_IsCPI(control) && ccnxControl_IsACK(control)) { + uint64_t sequenceNumber = ccnxControl_GetAckOriginalSequenceNumber(control); + if (sequenceNumber == expectedSequenceNumber) { + matchedSequenceNumber = true; + } + } + } + ccnxMetaMessage_Release(&message); + } else { + // this is likely some sort of error with the connection. + // should report this somehow. This case shows up from test_ccnx_PortalAPI. + result = false; + break; + } + } + } + + return result; +} + +static void +_ccnxPortal_Destroy(CCNxPortal **portalPtr) +{ + CCNxPortal *portal = *portalPtr; + + ccnxPortal_Flush(portal, CCNxStackTimeout_Never); + + ccnxPortalStack_Stop(portal->stack); + ccnxPortalStack_Release((CCNxPortalStack **) &portal->stack); +} + +parcObject_ExtendPARCObject(CCNxPortal, _ccnxPortal_Destroy, NULL, NULL, NULL, NULL, NULL, NULL); + +parcObject_ImplementAcquire(ccnxPortal, CCNxPortal); + +parcObject_ImplementRelease(ccnxPortal, CCNxPortal); + +CCNxPortal * +ccnxPortal_Create(const CCNxPortalAttributes *attributes, const CCNxPortalStack *portalStack) +{ + CCNxPortal *result = parcObject_CreateInstance(CCNxPortal); + + if (result != NULL) { + result->stack = portalStack; + result->status.eof = false; + result->status.error = 0; + } + + if (ccnxPortalStack_Start(portalStack) == false) { + parcObject_Release((void **) &result); + } + + return result; +} + +const CCNxPortalStatus * +ccnxPortal_GetStatus(const CCNxPortal *portal) +{ + return &portal->status; +} + +bool +ccnxPortal_SetAttributes(CCNxPortal *portal, const CCNxPortalAttributes *attributes) +{ + return ccnxPortalStack_SetAttributes(portal->stack, attributes); +} + +int +ccnxPortal_GetFileId(const CCNxPortal *portal) +{ + return ccnxPortalStack_GetFileId(portal->stack); +} + +bool +ccnxPortal_Listen(CCNxPortal *restrict portal, const CCNxName *restrict name, const time_t secondsToLive, const CCNxStackTimeout *microSeconds) +{ + bool result = ccnxPortalStack_Listen(portal->stack, name, microSeconds); + + if (result == true) { + _ccnxPortal_SetAnchor(portal, name, secondsToLive); + } + + portal->status.error = (result == true) ? 0 : ccnxPortalStack_GetErrorCode(portal->stack); + + return result; +} + +bool +ccnxPortal_Ignore(CCNxPortal *portal, const CCNxName *name, const CCNxStackTimeout *microSeconds) +{ + bool result = ccnxPortalStack_Ignore(portal->stack, name, microSeconds); + + portal->status.error = (result == true) ? 0 : ccnxPortalStack_GetErrorCode(portal->stack); + + return result; +} + +bool +ccnxPortal_Send(CCNxPortal *restrict portal, const CCNxMetaMessage *restrict message, const CCNxStackTimeout *timeout) +{ + bool result = ccnxPortalStack_Send(portal->stack, message, timeout); + + portal->status.error = result ? 0 : ccnxPortalStack_GetErrorCode(portal->stack); + return result; +} + +CCNxMetaMessage * +ccnxPortal_Receive(CCNxPortal *portal, const CCNxStackTimeout *timeout) +{ + CCNxMetaMessage *result = ccnxPortalStack_Receive(portal->stack, timeout); + + // This modal operation of Portal is awkward. + // Messages are interest = content-object, while Chunked is interest = {content-object_1, content-object_2, ...} + // If chunked. + // If Content Object + // If this content object is the final chunk + // Set EOF + + portal->status.error = (result != NULL) ? 0 : ccnxPortalStack_GetErrorCode(portal->stack); + return result; +} + +const PARCKeyId * +ccnxPortal_GetKeyId(const CCNxPortal *portal) +{ + return ccnxPortalStack_GetKeyId(portal->stack); +} + +bool +ccnxPortal_IsEOF(const CCNxPortal *portal) +{ + return portal->status.eof; +} + +bool +ccnxPortal_IsError(const CCNxPortal *portal) +{ + return portal->status.error != 0; +} + +int +ccnxPortal_GetError(const CCNxPortal *portal) +{ + return portal->status.error; +} |