- MMS client: add asynchronous function for MMS identify service

pull/93/head
Michael Zillgith 7 years ago
parent 7600c0f3cf
commit c80a87d5e8

@ -856,6 +856,14 @@ MmsConnection_getLocalDetail(MmsConnection self);
MmsServerIdentity* MmsServerIdentity*
MmsConnection_identify(MmsConnection self, MmsError* mmsError); 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 void
MmsServerIdentity_destroy(MmsServerIdentity* self); MmsServerIdentity_destroy(MmsServerIdentity* self);

@ -71,7 +71,8 @@ typedef enum {
MMS_CALL_TYPE_DEFINE_NVL, MMS_CALL_TYPE_DEFINE_NVL,
MMS_CALL_TYPE_DELETE_NVL, MMS_CALL_TYPE_DELETE_NVL,
MMS_CALL_TYPE_GET_VAR_ACCESS_ATTR, MMS_CALL_TYPE_GET_VAR_ACCESS_ATTR,
MMS_CALL_TYPE_GET_SERVER_STATUS MMS_CALL_TYPE_GET_SERVER_STATUS,
MMS_CALL_TYPE_IDENTIFY
} eMmsOutstandingCallType; } eMmsOutstandingCallType;
struct sMmsOutstandingCall struct sMmsOutstandingCall
@ -277,8 +278,8 @@ mmsClient_createDeleteAssociationSpecificNamedVariableListRequest(
void void
mmsClient_createIdentifyRequest(uint32_t invokeId, ByteBuffer* request); mmsClient_createIdentifyRequest(uint32_t invokeId, ByteBuffer* request);
MmsServerIdentity* bool
mmsClient_parseIdentifyResponse(MmsConnection self); mmsClient_parseIdentifyResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, uint32_t invokeId, MmsConnection_IdentifyHandler handler, void* parameter);
void void
mmsClient_createStatusRequest(uint32_t invokeId, ByteBuffer* request, bool extendedDerivation); mmsClient_createStatusRequest(uint32_t invokeId, ByteBuffer* request, bool extendedDerivation);

@ -931,6 +931,24 @@ handleAsyncResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, M
handler(outstandingCall->invokeId, outstandingCall->userParameter, err, vmdLogicalStatus, vmdPhysicalStatus); 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); removeFromOutstandingCalls(self, outstandingCall->invokeId);
@ -2679,31 +2697,86 @@ exit_function:
return invokeId; 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* MmsServerIdentity*
MmsConnection_identify(MmsConnection self, MmsError* mmsError) MmsConnection_identify(MmsConnection self, MmsError* mmsError)
{ {
MmsServerIdentity* identity = NULL; 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, &parameter);
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) { if (getAssociationState(self) != MMS_STATE_CONNECTED) {
if (mmsError)
*mmsError = MMS_ERROR_CONNECTION_LOST; *mmsError = MMS_ERROR_CONNECTION_LOST;
goto exit_function; goto exit_function;
} }
ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient); ByteBuffer* payload = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
uint32_t invokeId = getNextInvokeId(self); invokeId = getNextInvokeId(self);
mmsClient_createIdentifyRequest(invokeId, payload); mmsClient_createIdentifyRequest(invokeId, payload);
ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload, mmsError); MmsError err = sendAsyncRequest(self, invokeId, payload, MMS_CALL_TYPE_IDENTIFY, handler, parameter);
if (responseMessage != NULL)
identity = mmsClient_parseIdentifyResponse(self);
releaseResponse(self); if (mmsError)
*mmsError = err;
exit_function: exit_function:
return identity; return invokeId;
} }
struct getServerStatusParameters struct getServerStatusParameters

@ -49,14 +49,12 @@ mmsClient_createIdentifyRequest(uint32_t invokeId, ByteBuffer* request)
request->size = bufPos; request->size = bufPos;
} }
MmsServerIdentity* bool
mmsClient_parseIdentifyResponse(MmsConnection self) mmsClient_parseIdentifyResponse(MmsConnection self, ByteBuffer* response, uint32_t bufPos, uint32_t invokeId, MmsConnection_IdentifyHandler handler, void* parameter)
{ {
uint8_t* buffer = self->lastResponse->buffer; uint8_t* buffer = ByteBuffer_getBuffer(response);
int maxBufPos = self->lastResponse->size; int maxBufPos = ByteBuffer_getSize(response);
int bufPos = self->lastResponseBufPos;
int length; int length;
MmsServerIdentity* identityInfo = NULL;
uint8_t tag = buffer[bufPos++]; uint8_t tag = buffer[bufPos++];
if (tag != 0xa2) if (tag != 0xa2)
@ -73,6 +71,10 @@ mmsClient_parseIdentifyResponse(MmsConnection self)
goto exit_error; goto exit_error;
} }
char vendorNameBuf[100];
char modelNameBuf[100];
char revisionBuf[100];
char* vendorName = NULL; char* vendorName = NULL;
char* modelName = NULL; char* modelName = NULL;
char* revision = NULL; char* revision = NULL;
@ -85,15 +87,15 @@ mmsClient_parseIdentifyResponse(MmsConnection self)
switch (tag) { switch (tag) {
case 0x80: /* vendorName */ case 0x80: /* vendorName */
vendorName = StringUtils_createStringFromBuffer(buffer + bufPos, length); vendorName = StringUtils_createStringFromBufferInBuffer(vendorNameBuf, buffer + bufPos, length);
bufPos += length; bufPos += length;
break; break;
case 0x81: /* modelName */ case 0x81: /* modelName */
modelName = StringUtils_createStringFromBuffer(buffer + bufPos, length); modelName = StringUtils_createStringFromBufferInBuffer(modelNameBuf, buffer + bufPos, length);
bufPos += length; bufPos += length;
break; break;
case 0x82: /* revision */ case 0x82: /* revision */
revision = StringUtils_createStringFromBuffer(buffer + bufPos, length); revision = StringUtils_createStringFromBufferInBuffer(revisionBuf, buffer + bufPos, length);
bufPos += length; bufPos += length;
break; break;
case 0x83: /* list of abstract syntaxes */ 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; return true;
identityInfo->modelName = modelName;
identityInfo->revision = revision;
exit_error: exit_error:
return identityInfo; return false;
} }

@ -1,7 +1,7 @@
/* /*
* mms_client_status.c * mms_client_status.c
* *
* Copyright 2013, 2014 Michael Zillgith * Copyright 2013-2018 Michael Zillgith
* *
* This file is part of libIEC61850. * This file is part of libIEC61850.
* *

Loading…
Cancel
Save