AwaError OperationCommon_AddPathToObjectsTree(TreeNode objectsTree, const char * path, TreeNode * resultNode) { AwaError result = AwaError_Unspecified; if (objectsTree != NULL) { if (path != NULL) { if (Path_IsValid(path)) { // Drop paths that are already represented // E.g. /3/0/0 should be dropped if /3/0 is already present if (ObjectsTree_IsPathCovered(objectsTree, path, resultNode) == false) { // if a new path that covers existing paths is added, remove any existing path nodes TreeNode existing = NULL; if (ObjectsTree_FindPathNode(objectsTree, path, &existing) == InternalError_Success) { if (resultNode != NULL) { *resultNode = existing; } ObjectsTree_RemovePathNodes(existing); LogDebug("Removing nodes below %s", path); result = AwaError_Success; } else { if (ObjectsTree_AddPath(objectsTree, path, resultNode) == InternalError_Success) { result = AwaError_Success; } else { result = LogErrorWithEnum(AwaError_Internal, "AddPath failed"); } } } else { LogDebug("Dropping path %s", path); result = AwaError_Success; } } else { result = LogErrorWithEnum(AwaError_PathInvalid, "Path %s is not valid", path); } } else { result = LogErrorWithEnum(AwaError_PathInvalid, "Path is NULL"); } } else { result = LogErrorWithEnum(AwaError_OperationInvalid, "Objects Tree is NULL"); } return result; }
AwaError ChangeSet_GetExecuteArguments(const AwaChangeSet *changeSet, const char * path, AwaExecuteArguments * arguments) { AwaError error = AwaError_Unspecified; if (changeSet != NULL) { if (arguments != NULL) { AwaOpaque executePayload = {NULL, 0}; error = AwaChangeSet_GetValueAsOpaque(changeSet, path, &executePayload); if (error == AwaError_Success) { arguments->Data = executePayload.Data; arguments->Size = executePayload.Size; } } else { error = LogErrorWithEnum(AwaError_OperationInvalid, "Arguments are NULL"); } } else { error = LogErrorWithEnum(AwaError_OperationInvalid, "ChangeSet is NULL"); } return error; }
OperationCommon * OperationCommon_NewWithExistingObjectsTree(const Session * session, SessionType sessionType, TreeNode objectsTree) { OperationCommon * operation = NULL; if (session != NULL) { operation = Awa_MemAlloc(sizeof(*operation)); if (operation != NULL) { memset(operation, 0, sizeof(*operation)); operation->Session = session; operation->SessionType = sessionType; operation->ObjectsTree = objectsTree; if (operation->ObjectsTree != NULL) { LogNew("OperationCommon", operation); } else { LogErrorWithEnum(AwaError_Internal, "Unable to initialise operation"); Awa_MemSafeFree(operation); operation = NULL; } } else { LogErrorWithEnum(AwaError_OutOfMemory); } } else { LogErrorWithEnum(AwaError_SessionInvalid, "Session is NULL"); } return operation; }
void StringIterator_Add(StringIterator * iterator, const char * string) { if (iterator != NULL) { if (string != NULL) { // allocate memory, to be managed by iterator: char * newString = strdup(string); if (newString != NULL) { Iterator_Add(iterator->Iterator, newString); } else { LogErrorWithEnum(AwaError_Internal, "unable to allocate memory for string"); } } else { LogErrorWithEnum(AwaError_Internal, "string is NULL"); } } else { LogErrorWithEnum(AwaError_IteratorInvalid, "iterator is NULL"); } }
const SessionCommon * OperationCommon_GetSessionCommon(const OperationCommon * operation) { const SessionCommon * sessionCommon = NULL; if (operation != NULL) { // to get the common Session, we must know what kind of session it is SessionType sessionType = SessionType_Invalid; const Session * sessionBlind = OperationCommon_GetSession(operation, &sessionType); // use SessionType to safely cast and dereference the Session pointer switch (sessionType) { case SessionType_Client: sessionCommon = ClientSession_GetSessionCommon((const AwaClientSession *)sessionBlind); break; case SessionType_Server: sessionCommon = ServerSession_GetSessionCommon((const AwaServerSession *)sessionBlind); break; default: LogErrorWithEnum(AwaError_Internal, "Invalid SessionType %d", sessionType); break; } } else { LogErrorWithEnum(AwaError_OperationInvalid, "operation is NULL"); } return sessionCommon; }
AwaError ResponseCommon_CheckForErrors(const ResponseCommon * response) { AwaError result = AwaError_Success; if (response != NULL) { if (response->ObjectsNode != NULL) { TreeNode currentNode = response->ObjectsNode; if (currentNode != NULL) { while ((currentNode = ObjectsTree_GetNextLeafNode(currentNode)) != NULL) { // check for a Result tag TreeNode resultNode = Xml_Find(currentNode, "Result"); if (resultNode != NULL) { TreeNode errorNode = Xml_Find(resultNode, "Error"); if (errorNode != NULL) { AwaError error = Error_FromString((const char *)TreeNode_GetValue(errorNode)); if (error != AwaError_Success) { result = AwaError_Response; } // keep looking; examine all leaf nodes } else { // result without error node - error result = LogErrorWithEnum(AwaError_ResponseInvalid, "Response Result has missing Error node"); break; } } else { // leaf without result node - error result = LogErrorWithEnum(AwaError_ResponseInvalid, "Response has missing Result node"); break; } } } else { result = LogErrorWithEnum(AwaError_Internal, "Response has no objects tree"); } } else { result = LogErrorWithEnum(AwaError_Internal, "Response has no objects node"); } } else { result = LogErrorWithEnum(AwaError_ResponseInvalid, "response is NULL"); } return result; }
ResponseCommon * ResponseCommon_New(const OperationCommon * operation, TreeNode objectsNode) { ResponseCommon * response = NULL; if (operation != NULL) { if (objectsNode != NULL) { response = Awa_MemAlloc(sizeof(*response)); if (response != NULL) { memset(response, 0, sizeof(*response)); response->OperationCommon = operation; response->ObjectsNode = Tree_Copy(objectsNode); // build the Values data structure if (ResponseCommon_BuildValues(response) == AwaError_Success) { // not all responses have Values, so success includes no values } else { // there was an error building values LogDebug("Failed to build response values - continuing"); } if (ResponseCommon_BuildPathResults(response) == AwaError_Success) { // not all responses have path results } else { // there was an error building values LogErrorWithEnum(AwaError_ResponseInvalid, "Failed to build path results - continuing"); } response->NulledValues = Map_New(); LogNew("ResponseCommon", response); } else { LogErrorWithEnum(AwaError_OutOfMemory); } } else { LogError("Content Response is NULL"); } } else { LogError("Operation is NULL"); } return response; }
AwaError AwaClientSetOperation_CreateObjectInstance(AwaClientSetOperation * operation, const char * path) { AwaError result = AwaError_Unspecified; if (path != NULL) { AwaObjectID objectID; AwaResourceID resourceID; if (Path_IsValid(path)) { objectID = Path_GetObjectID(path); resourceID = Path_GetResourceID(path); if ((objectID != AWA_INVALID_ID) && (resourceID == AWA_INVALID_ID)) { if (operation != NULL) { TreeNode resultNode; if ((result = OperationCommon_AddPathV2(operation->Common, path, &resultNode)) == AwaError_Success && resultNode != NULL) { //NB: if object instance ID isn't specified in the path we have to check the response for the generated ID if (ClientSetOperation_AddCreate(resultNode) == InternalError_Success) { result = AwaError_Success; } else { result = LogErrorWithEnum(AwaError_Internal, "Failed to add value to path"); } } } else { result = LogErrorWithEnum(AwaError_OperationInvalid, "Operation is NULL"); } } else { result = LogErrorWithEnum(AwaError_PathInvalid, "%s is not a valid object or object instance path", path); } } else { result = LogErrorWithEnum(AwaError_PathInvalid, "%s is not a valid path", path); } } else { result = LogErrorWithEnum(AwaError_PathInvalid, "Path is NULL"); } return result; }
AwaClientSubscribeOperation * AwaClientSubscribeOperation_New(const AwaClientSession * session) { AwaClientSubscribeOperation * operation = NULL; if (session != NULL) { if (ClientSession_IsConnected(session) != false) { operation = Awa_MemAlloc(sizeof(*operation)); if (operation != NULL) { memset(operation, 0, sizeof(*operation)); operation->Common = OperationCommon_NewWithClientSession(session); if (operation->Common != NULL) { operation->Subscribers = Map_New(); if (operation->Subscribers != NULL) { LogNew("AwaClientSubscribeOperation", operation); } else { LogErrorWithEnum(AwaError_OutOfMemory, "Could not create subscriber list."); Awa_MemSafeFree(operation); operation = NULL; } } else { LogErrorWithEnum(AwaError_Internal, "Unable to initialise operation."); Awa_MemSafeFree(operation); operation = NULL; } } else { LogErrorWithEnum(AwaError_OutOfMemory); } } else { LogError("Session is not connected"); } } else { LogError("Session is NULL"); } return operation; }
AwaError AwaServerExecuteOperation_AddPath(AwaServerExecuteOperation * operation, const char * clientID, const char * path, const AwaExecuteArguments * arguments) { AwaError result = AwaError_Unspecified; if (operation != NULL) { if (Path_IsValidForResource(path)) { TreeNode resultNode = NULL; if ((result = ServerOperation_AddPath(operation->ServerOperation, clientID, path, &resultNode)) == AwaError_Success) { if (resultNode != NULL) { char * encodedValue = NULL; if (arguments != NULL && arguments->Size > 0) { encodedValue = xmlif_EncodeValue(AwaResourceType_Opaque, arguments->Data, arguments->Size); } if (encodedValue == NULL || SetWriteCommon_SetResourceNodeValue(resultNode, encodedValue) == InternalError_Success) { result = AwaError_Success; } else { result = LogErrorWithEnum(AwaError_Internal, "Failed to set resource value"); } if (encodedValue) { Awa_MemSafeFree(encodedValue); } } else { result = LogErrorWithEnum(AwaError_Internal, "AddPath failed to return result node"); } } } else { result = LogErrorWithEnum(AwaError_PathInvalid, "%s is not a valid path to an executable resource", path); } } else { result = LogErrorWithEnum(AwaError_OperationInvalid, "Operation is NULL"); } return result; }
static AwaError ClientSetOperation_AddValues(AwaClientSetOperation * operation, const char * path, const AwaArray * array, AwaResourceType type) { AwaError result = AwaError_Unspecified; AwaArrayIterator * iterator = ArrayIterator_New(array); if (iterator) { while(ArrayIterator_Next(iterator)) { AwaArrayIndex index = ArrayIterator_GetIndex(iterator); void * value = ArrayIterator_GetValue(iterator); size_t length = ArrayIterator_GetValueLength(iterator); if (type == AwaResourceType_OpaqueArray) { AwaOpaque * opaque = value; value = opaque->Data; length = opaque->Size; } LogDebug("Adding value %p", value); if (value) { result = ClientSetOperation_AddValue(operation, path, index, value, length, type, SetArrayMode_Replace); if (result != AwaError_Success) { LogError("Unable to add array resource Instance"); break; } } else { result = LogErrorWithEnum(AwaError_Internal , "Problem with array"); break; } } ArrayIterator_Free(&iterator); } else { result = LogErrorWithEnum(AwaError_OperationInvalid, "Operation is NULL"); } return result; }
AwaError AwaServerSession_Process(AwaServerSession * session, AwaTimeout timeout) { AwaError result = AwaError_Unspecified; if (session != NULL) { while (IPC_WaitForNotification(ServerSession_GetChannel(session), timeout) == AwaError_Success) { IPCMessage * notification; if (IPC_ReceiveNotification(ServerSession_GetChannel(session), ¬ification) == AwaError_Success) { if (!Queue_Push(session->NotificationQueue, notification)) { // Queue full? IPCMessage_Free(¬ification); } } // we have received at least 1 packet, so we no longer have any reason to wait // if there are no more in the pipeline. timeout = 0; } result = AwaError_Success; } else { LogErrorWithEnum(AwaError_SessionInvalid, "session is NULL"); } return result; }
// FIXME Currently The client is using the old xml spec and therefore can't be used with the new objects tree. // This is a temporary workaround to prevent error messages when the response does not contain an 'Objects' node ResponseCommon * ResponseCommon_NewClient(const OperationCommon * operation, TreeNode objectsNode) { ResponseCommon * response = NULL; if (operation != NULL) { if (objectsNode != NULL) { response = Awa_MemAlloc(sizeof(*response)); if (response != NULL) { memset(response, 0, sizeof(*response)); response->OperationCommon = operation; response->ObjectsNode = Tree_Copy(objectsNode); LogNew("ResponseCommon", response); } else { LogErrorWithEnum(AwaError_OutOfMemory); } } else { LogError("Content Response is NULL"); } } else { LogError("Operation is NULL"); } return response; }
AwaChangeSet * ChangeSet_NewWithClientID(Session * session, SessionType sessionType, TreeNode objectsTree, const char * clientID) { AwaChangeSet * changeSet = NULL; if (objectsTree != NULL) { changeSet = Awa_MemAlloc(sizeof(*changeSet)); if (changeSet != NULL) { memset(changeSet, 0, sizeof(*changeSet)); changeSet->OperationCommon = OperationCommon_New(session, sessionType); if (changeSet->OperationCommon != NULL) { changeSet->ResponseCommon = ResponseCommon_New(changeSet->OperationCommon, objectsTree); if (changeSet->ResponseCommon != NULL) { changeSet->ClientID = clientID; LogNew("AwaChangeSet New", changeSet); } else { LogErrorWithEnum(AwaError_OutOfMemory); OperationCommon_Free(&changeSet->OperationCommon); Awa_MemSafeFree(changeSet); changeSet = NULL; } } else { LogErrorWithEnum(AwaError_OutOfMemory); Awa_MemSafeFree(changeSet); changeSet = NULL; } } else { LogErrorWithEnum(AwaError_OutOfMemory); } } else { LogErrorWithEnum(AwaError_OperationInvalid, "Objects tree is NULL"); } return changeSet; }
static const Session * AwaChangeSet_GetSession(const AwaChangeSet * changeSet, SessionType sessionType) { const Session * session = NULL; if (changeSet != NULL) { SessionType actualSessionType = SessionType_Invalid; session = OperationCommon_GetSession(ResponseCommon_GetOperation(changeSet->ResponseCommon), &actualSessionType); if (sessionType != actualSessionType) { LogErrorWithEnum(AwaError_OperationInvalid, "Changeset does not hold a session of type %d. Requesting Session type %d\n", actualSessionType, sessionType); session = NULL; } } else { LogErrorWithEnum(AwaError_OperationInvalid, "ChangeSet is NULL"); } return session; }
AwaServerExecuteOperation * AwaServerExecuteOperation_New(const AwaServerSession * session) { // AwaServerExecuteResponse is an alias for ResponseCommon AwaServerExecuteOperation * operation = NULL; if (session != NULL) { if (ServerSession_IsConnected(session) != false) { operation = Awa_MemAlloc(sizeof(*operation)); if (operation != NULL) { memset(operation, 0, sizeof(*operation)); operation->ServerOperation = ServerOperation_New(session); if (operation->ServerOperation != NULL) { LogNew("AwaServerExecuteOperation", operation); } else { LogErrorWithEnum(AwaError_Internal, "Unable to initialise operation"); Awa_MemSafeFree(operation); operation = NULL; } } else { LogErrorWithEnum(AwaError_OutOfMemory); } } else { LogErrorWithEnum(AwaError_SessionInvalid); } } else { LogErrorWithEnum(AwaError_SessionInvalid, "Session is NULL"); } return operation; }
static AwaClientSubscription * ClientSubscription_New(const char * path, void * callback, void * context, AwaSubscribeType subscribeType) { AwaClientSubscription * subscription = NULL; if ((path != NULL) && (callback != NULL)) { subscription = Awa_MemAlloc(sizeof(*subscription)); if (subscription != NULL) { subscription->Path = strdup(path); if (subscription->Path != NULL) { subscription->Operations = List_New(); if (subscription->Operations != NULL) { subscription->Callback = (void *)callback; subscription->Context = context; subscription->Session = NULL; subscription->Type = subscribeType; } else { free((void *)subscription->Path); Awa_MemSafeFree(subscription); LogErrorWithEnum(AwaError_OutOfMemory); subscription = NULL; } } else { Awa_MemSafeFree(subscription); LogErrorWithEnum(AwaError_OutOfMemory); subscription = NULL; } } else { LogErrorWithEnum(AwaError_OutOfMemory); } } return subscription; }
AwaServerListClientsOperation * AwaServerListClientsOperation_New(const AwaServerSession * session) { AwaServerListClientsOperation * operation = NULL; if (session != NULL) { if (ServerSession_IsConnected(session) != false) { operation = Awa_MemAlloc(sizeof(*operation)); if (operation != NULL) { memset(operation, 0, sizeof(*operation)); operation->ServerResponse = NULL; operation->ServerOperation = ServerOperation_New(session); if (operation->ServerOperation != NULL) { operation->ClientResponseMap = Map_New(); LogNew("AwaServerListClientsOperation", operation); } else { LogErrorWithEnum(AwaError_Internal, "Unable to initialise operation"); Awa_MemSafeFree(operation); operation = NULL; } } else { LogErrorWithEnum(AwaError_OutOfMemory); } } else { LogErrorWithEnum(AwaError_SessionNotConnected); } } else { LogError("Session is NULL"); } return operation; }
AwaError AwaServerSession_SetClientUpdateEventCallback(AwaServerSession * session, AwaServerClientUpdateEventCallback callback, void * context) { AwaError result = AwaError_Unspecified; if (session != NULL) { if (ServerEventsCallbackInfo_SetClientUpdateCallback(session->ServerEventsCallbackInfo, callback, context) == 0) { result = AwaError_Success; } else { result = LogErrorWithEnum(AwaError_Internal, "session->ServerEventsCallbackInfo is NULL"); } } else { result = LogErrorWithEnum(AwaError_SessionInvalid, "session is NULL"); } return result; }
static AwaError ClientSubscribeOperation_Add(AwaClientSubscribeOperation * operation, AwaClientSubscription * subscription, bool cancel) { AwaError result = AwaError_Unspecified; if (operation != NULL) { if (subscription != NULL) { AwaClientSubscription * existingSubscription = NULL; Map_Get(operation->Subscribers, subscription->Path, (void **)&existingSubscription); if (existingSubscription == NULL) { if (Map_Put(operation->Subscribers, subscription->Path, subscription)) { List_Add(subscription->Operations, operation); subscription->Cancel = cancel; result = AwaError_Success; } else { result = LogErrorWithEnum(AwaError_Internal, "Failed to add subscription to operation"); } } else { result = LogErrorWithEnum(AwaError_OperationInvalid, "A subscription already exists for path %s in the given operation.", subscription->Path); } } else { result = LogErrorWithEnum(AwaError_SubscriptionInvalid, "Subscription is NULL"); } } else { result = LogErrorWithEnum(AwaError_OperationInvalid, "Operation is NULL"); } return result; }
static void ClientSubscriberList_InvokeSubscribeCallback(MapType * subscribers, const char * path, const AwaChangeSet * changeSet) { AwaClientSubscription * subscription = NULL; Map_Get(subscribers, path, (void **)&subscription); if (subscription != NULL) { switch (subscription->Type) { case AwaSubscribeType_Change: { AwaClientSubscribeToChangeCallback callback = (AwaClientSubscribeToChangeCallback)subscription->Callback; callback(changeSet, subscription->Context); break; } case AwaSubscribeType_Execute: { AwaExecuteArguments arguments = {NULL, 0}; AwaError result = AwaError_Unspecified; if ((result = ChangeSet_GetExecuteArguments(changeSet, path, &arguments)) == AwaError_Success) { AwaClientSubscribeToExecuteCallback callback = (AwaClientSubscribeToExecuteCallback)subscription->Callback; callback(&arguments, subscription->Context); } else { LogErrorWithEnum(result, "Failed to get arguments from execute notification"); } break; } default: LogErrorWithEnum(AwaError_Unsupported, "Unsupported subscribe type: %d", subscription->Type); break; } } else { LogDebug("No subscription for path %s\n", path); } }
AwaError AwaServerSession_SetDefaultTimeout(AwaServerSession * session, AwaTimeout timeout) { AwaError result = AwaError_Unspecified; if (session != NULL) { SessionCommon * sessionCommon = ServerSession_GetSessionCommon(session); if (sessionCommon != NULL) { result = SessionCommon_SetDefaultTimeout(sessionCommon, timeout); } else { result = LogErrorWithEnum(AwaError_SessionInvalid, "sessionCommon is NULL"); } } else { result = LogErrorWithEnum(AwaError_SessionInvalid, "session is NULL"); } return result; }
AwaRegisteredEntityIterator * AwaServerListClientsResponse_NewRegisteredEntityIterator(const AwaServerListClientsResponse * response) { RegisteredEntityIterator * iterator = NULL; if (response != NULL) { iterator = RegisteredEntityIterator_New(response->Response); } else { LogErrorWithEnum(AwaError_ResponseInvalid, "response is NULL"); } return (AwaRegisteredEntityIterator *)iterator; }
AwaClientIterator * AwaServerListClientsOperation_NewClientIterator(const AwaServerListClientsOperation * operation) { AwaClientIterator * iterator = NULL; if (operation != NULL) { iterator = (AwaClientIterator *)ServerResponse_NewClientIterator(operation->ServerResponse); } else { LogErrorWithEnum(AwaError_OperationInvalid, "operation is NULL"); } return iterator; }
MapType * ServerSession_GetObservers(const AwaServerSession * session) { MapType * list = NULL; if (session != NULL) { list = session->Observers; } else { LogErrorWithEnum(AwaError_SessionInvalid, "session is NULL"); } return list; }
SessionCommon * ServerSession_GetSessionCommon(const AwaServerSession * session) { SessionCommon * common = NULL; if (session != NULL) { common = session->SessionCommon; } else { LogErrorWithEnum(AwaError_SessionInvalid, "session is NULL"); } return common; }
bool AwaServerSession_IsObjectDefined(const AwaServerSession * session, AwaObjectID objectID) { bool result = false; if (session != NULL) { result = SessionCommon_IsObjectDefined(session->SessionCommon, objectID); } else { LogErrorWithEnum(AwaError_SessionInvalid); } return result; }
const AwaResourceDefinition * ServerSession_GetResourceDefinitionFromPath(const AwaServerSession * session, const char * path) { const AwaResourceDefinition * result = NULL; if (session != NULL) { result = SessionCommon_GetResourceDefinitionFromPath(session->SessionCommon, path); } else { LogErrorWithEnum(AwaError_SessionInvalid); } return result; }
AwaError ServerSession_CheckResourceTypeFromPath(const AwaServerSession * session, const char * path, AwaResourceType expected) { AwaError result = AwaError_Unspecified; if (session != NULL) { result = SessionCommon_CheckResourceTypeFromPath(session->SessionCommon, path, expected); } else { LogErrorWithEnum(AwaError_SessionInvalid); } return result; }
AwaError AwaServerSession_PathToIDs(const AwaServerSession * session, const char * path, AwaObjectID * objectID, AwaObjectInstanceID * objectInstanceID, AwaResourceID * resourceID) { AwaError result = AwaError_Unspecified; if (session != NULL) { result = SessionCommon_PathToIDs(session->SessionCommon, path, objectID, objectInstanceID, resourceID); } else { result = LogErrorWithEnum(AwaError_SessionInvalid); } return result; }