From c80a87d5e8cc4f60acb4f52fca0a743ce92b5db6 Mon Sep 17 00:00:00 2001 From: Michael Zillgith Date: Tue, 11 Sep 2018 11:23:05 +0200 Subject: [PATCH] - MMS client: add asynchronous function for MMS identify service --- src/mms/inc/mms_client_connection.h | 8 ++ src/mms/inc_private/mms_client_internal.h | 7 +- .../iso_mms/client/mms_client_connection.c | 91 +++++++++++++++++-- src/mms/iso_mms/client/mms_client_identify.c | 34 ++++--- src/mms/iso_mms/client/mms_client_status.c | 2 +- 5 files changed, 115 insertions(+), 27 deletions(-) diff --git a/src/mms/inc/mms_client_connection.h b/src/mms/inc/mms_client_connection.h index fa7e70b1..fc964203 100644 --- a/src/mms/inc/mms_client_connection.h +++ b/src/mms/inc/mms_client_connection.h @@ -856,6 +856,14 @@ MmsConnection_getLocalDetail(MmsConnection self); MmsServerIdentity* MmsConnection_identify(MmsConnection self, MmsError* mmsError); +typedef void +(*MmsConnection_IdentifyHandler) (int invokeId, void* parameter, MmsError mmsError, + char* vendorName, char* modelName, char* revision); + +uint32_t +MmsConnection_identifyAsync(MmsConnection self, MmsError* mmsError, + MmsConnection_IdentifyHandler handler, void* parameter); + void MmsServerIdentity_destroy(MmsServerIdentity* self); diff --git a/src/mms/inc_private/mms_client_internal.h b/src/mms/inc_private/mms_client_internal.h index 832cdeef..db44e6b7 100644 --- a/src/mms/inc_private/mms_client_internal.h +++ b/src/mms/inc_private/mms_client_internal.h @@ -71,7 +71,8 @@ typedef enum { MMS_CALL_TYPE_DEFINE_NVL, MMS_CALL_TYPE_DELETE_NVL, MMS_CALL_TYPE_GET_VAR_ACCESS_ATTR, - MMS_CALL_TYPE_GET_SERVER_STATUS + MMS_CALL_TYPE_GET_SERVER_STATUS, + MMS_CALL_TYPE_IDENTIFY } eMmsOutstandingCallType; struct sMmsOutstandingCall @@ -277,8 +278,8 @@ mmsClient_createDeleteAssociationSpecificNamedVariableListRequest( void mmsClient_createIdentifyRequest(uint32_t invokeId, ByteBuffer* request); -MmsServerIdentity* -mmsClient_parseIdentifyResponse(MmsConnection self); +bool +mmsClient_parseIdentifyResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, uint32_t invokeId, MmsConnection_IdentifyHandler handler, void* parameter); void mmsClient_createStatusRequest(uint32_t invokeId, ByteBuffer* request, bool extendedDerivation); diff --git a/src/mms/iso_mms/client/mms_client_connection.c b/src/mms/iso_mms/client/mms_client_connection.c index e36ff01e..8a63e3ca 100644 --- a/src/mms/iso_mms/client/mms_client_connection.c +++ b/src/mms/iso_mms/client/mms_client_connection.c @@ -931,6 +931,24 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M handler(outstandingCall->invokeId, outstandingCall->userParameter, err, vmdLogicalStatus, vmdPhysicalStatus); } } + else if (outstandingCall->type == MMS_CALL_TYPE_IDENTIFY) { + MmsConnection_IdentifyHandler handler = + (MmsConnection_IdentifyHandler) outstandingCall->userCallback; + + if (err != MMS_ERROR_NONE) { + handler(outstandingCall->invokeId, outstandingCall->userParameter, err, NULL, NULL, NULL); + } + else { + + if (mmsClient_parseIdentifyResponse(self, response, bufPos, outstandingCall->invokeId, handler, + outstandingCall->userParameter) == false) + { + handler(outstandingCall->invokeId, outstandingCall->userParameter, MMS_ERROR_PARSING_RESPONSE, + NULL, NULL, NULL); + } + + } + } removeFromOutstandingCalls(self, outstandingCall->invokeId); @@ -2679,31 +2697,86 @@ exit_function: return invokeId; } +struct identifyParameters +{ + Semaphore waitForResponse; + MmsError err; + MmsServerIdentity* identify; +}; + +static void +identifyHandler(int invokeId, void* parameter, MmsError mmsError, char* vendorName, char* modelName, char* revision) +{ + struct identifyParameters* parameters = (struct identifyParameters*) parameter; + + parameters->err = mmsError; + + parameters->identify = (MmsServerIdentity*) GLOBAL_MALLOC(sizeof(MmsServerIdentity)); + parameters->identify->vendorName = StringUtils_copyString(vendorName); + parameters->identify->modelName = StringUtils_copyString(modelName); + parameters->identify->revision = StringUtils_copyString(revision); + + /* unblock user thread */ + Semaphore_post(parameters->waitForResponse); +} + + MmsServerIdentity* MmsConnection_identify(MmsConnection self, MmsError* mmsError) { MmsServerIdentity* identity = NULL; + struct identifyParameters parameter; + + MmsError err = MMS_ERROR_NONE; + + parameter.waitForResponse = Semaphore_create(1); + parameter.err = MMS_ERROR_NONE; + parameter.identify = NULL; + + Semaphore_wait(parameter.waitForResponse); + + MmsConnection_identifyAsync(self, &err, identifyHandler, ¶meter); + + if (err == MMS_ERROR_NONE) { + Semaphore_wait(parameter.waitForResponse); + err = parameter.err; + identity = parameter.identify; + } + + Semaphore_destroy(parameter.waitForResponse); + + if (mmsError) + *mmsError = err; + + return identity; +} + +uint32_t +MmsConnection_identifyAsync(MmsConnection self, MmsError* mmsError, + MmsConnection_IdentifyHandler handler, void* parameter) +{ + uint32_t invokeId = 0; + if (getAssociationState(self) != MMS_STATE_CONNECTED) { - *mmsError = MMS_ERROR_CONNECTION_LOST; + if (mmsError) + *mmsError = MMS_ERROR_CONNECTION_LOST; goto exit_function; } ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient); - uint32_t invokeId = getNextInvokeId(self); + invokeId = getNextInvokeId(self); mmsClient_createIdentifyRequest(invokeId, payload); - ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError); - - if (responseMessage != NULL) - identity = mmsClient_parseIdentifyResponse(self); + MmsError err = sendAsyncRequest(self, invokeId, payload, MMS_CALL_TYPE_IDENTIFY, handler, parameter); - releaseResponse(self); + if (mmsError) + *mmsError = err; - exit_function: - return identity; +exit_function: + return invokeId; } struct getServerStatusParameters diff --git a/src/mms/iso_mms/client/mms_client_identify.c b/src/mms/iso_mms/client/mms_client_identify.c index dade11dc..79543585 100644 --- a/src/mms/iso_mms/client/mms_client_identify.c +++ b/src/mms/iso_mms/client/mms_client_identify.c @@ -49,14 +49,12 @@ mmsClient_createIdentifyRequest(uint32_t invokeId, ByteBuffer* request) request->size = bufPos; } -MmsServerIdentity* -mmsClient_parseIdentifyResponse(MmsConnection self) +bool +mmsClient_parseIdentifyResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, uint32_t invokeId, MmsConnection_IdentifyHandler handler, void* parameter) { - uint8_t* buffer = self->lastResponse->buffer; - int maxBufPos = self->lastResponse->size; - int bufPos = self->lastResponseBufPos; + uint8_t* buffer = ByteBuffer_getBuffer(response); + int maxBufPos = ByteBuffer_getSize(response); int length; - MmsServerIdentity* identityInfo = NULL; uint8_t tag = buffer[bufPos++]; if (tag != 0xa2) @@ -73,6 +71,10 @@ mmsClient_parseIdentifyResponse(MmsConnection self) goto exit_error; } + char vendorNameBuf[100]; + char modelNameBuf[100]; + char revisionBuf[100]; + char* vendorName = NULL; char* modelName = NULL; char* revision = NULL; @@ -85,15 +87,15 @@ mmsClient_parseIdentifyResponse(MmsConnection self) switch (tag) { case 0x80: /* vendorName */ - vendorName = StringUtils_createStringFromBuffer(buffer + bufPos, length); + vendorName = StringUtils_createStringFromBufferInBuffer(vendorNameBuf, buffer + bufPos, length); bufPos += length; break; case 0x81: /* modelName */ - modelName = StringUtils_createStringFromBuffer(buffer + bufPos, length); + modelName = StringUtils_createStringFromBufferInBuffer(modelNameBuf, buffer + bufPos, length); bufPos += length; break; case 0x82: /* revision */ - revision = StringUtils_createStringFromBuffer(buffer + bufPos, length); + revision = StringUtils_createStringFromBufferInBuffer(revisionBuf, buffer + bufPos, length); bufPos += length; break; case 0x83: /* list of abstract syntaxes */ @@ -105,14 +107,18 @@ mmsClient_parseIdentifyResponse(MmsConnection self) } } - identityInfo = (MmsServerIdentity*) GLOBAL_MALLOC(sizeof(MmsServerIdentity)); +// identityInfo = (MmsServerIdentity*) GLOBAL_MALLOC(sizeof(MmsServerIdentity)); +// +// identityInfo->vendorName = vendorName; +// identityInfo->modelName = modelName; +// identityInfo->revision = revision; + + handler(invokeId, parameter, MMS_ERROR_NONE, vendorName, modelName, revision); - identityInfo->vendorName = vendorName; - identityInfo->modelName = modelName; - identityInfo->revision = revision; + return true; exit_error: - return identityInfo; + return false; } diff --git a/src/mms/iso_mms/client/mms_client_status.c b/src/mms/iso_mms/client/mms_client_status.c index 288bbafe..392fc665 100644 --- a/src/mms/iso_mms/client/mms_client_status.c +++ b/src/mms/iso_mms/client/mms_client_status.c @@ -1,7 +1,7 @@ /* * mms_client_status.c * - * Copyright 2013, 2014 Michael Zillgith + * Copyright 2013-2018 Michael Zillgith * * This file is part of libIEC61850. *