/* * mms_server_connection.c * * Copyright 2013-2018 Michael Zillgith * * This file is part of libIEC61850. * * libIEC61850 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libIEC61850 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libIEC61850. If not, see . * * See COPYING file for the complete license text. * * * MMS client connection handling code for libiec61850. * * Handles a MMS client connection. */ #include "libiec61850_platform_includes.h" #include "mms_server_internal.h" #include "iso_server.h" #include "ber_encoder.h" #include "ber_decode.h" /********************************************************************************************** * MMS Common support functions *********************************************************************************************/ #define MMS_REJECT_CONFIRMED_REQUEST 1 #define MMS_REJECT_CONFIRMED_RESPONSE 2 #define MMS_REJECT_CONFIRMED_ERROR 3 #define MMS_REJECT_UNCONFIRMED 4 #define MMS_REJECT_PDU_ERROR 5 #define MMS_REJECT_CANCEL_REQUEST 6 #define MMS_REJECT_CANCEL_RESPONSE 7 #define MMS_REJECT_CANCEL_ERROR 8 #define MMS_REJECT_CONCLUDE_REQUEST 9 #define MMS_REJECT_CONCLUDE_RESPONSE 10 #define MMS_REJECT_CONCLUDE_ERROR 11 #define MMS_REJECT_CONFIRMED_REQUEST_OTHER 0 #define MMS_REJECT_CONFIRMED_REQUEST_UNRECOGNIZED_SERVICE 1 #define MMS_REJECT_CONFIRMED_REQUEST_UNRECOGNIZED_MODIFIER 2 #define MMS_REJECT_CONFIRMED_REQUEST_INVALID_INVOKE_ID 3 #define MMS_REJECT_CONFIRMED_REQUEST_INVALID_ARGUMENT 4 #define MMS_REJECT_CONFIRMED_REQUEST_INVALID_MODIFIER 5 #define MMS_REJECT_CONFIRMED_REQUEST_MAX_SERV_OUTSTANDING_EXCEEDED 6 #define MMS_REJECT_CONFIRMED_REQUEST_MAX_RECURSION_EXCEEDED 8 #define MMS_REJECT_CONFIRMED_REQUEST_VALUE_OUT_OF_RANGE 9 #define MMS_REJECT_PDU_ERROR_UNKNOWN_PDU_TYPE 0 #define MMS_REJECT_PDU_ERROR_INVALID_PDU 1 #define MMS_REJECT_PDU_ERROR_ILLEGAL_ACSI_MAPPING 2 static void mmsMsg_encodeMmsRejectPdu(uint32_t* invokeId, int rejectType, int rejectReason, ByteBuffer* response) { int bufPos = 0; uint8_t* buffer = response->buffer; uint32_t invokeIdLength = 0; uint32_t rejectPduLength = 3; if (invokeId != NULL) { invokeIdLength = BerEncoder_UInt32determineEncodedSize(*invokeId); rejectPduLength += 2 + invokeIdLength; } /* Encode reject PDU */ bufPos = BerEncoder_encodeTL(0xa4, rejectPduLength, buffer, bufPos); if (invokeId != NULL) { /* original invokeId */ bufPos = BerEncoder_encodeTL(0x80, invokeIdLength, buffer, bufPos); bufPos = BerEncoder_encodeUInt32(*invokeId, buffer, bufPos); } buffer[bufPos++] = (uint8_t) (0x80 + rejectType); buffer[bufPos++] = 0x01; buffer[bufPos++] = (uint8_t) rejectReason; response->size = bufPos; } void mmsMsg_createMmsRejectPdu(uint32_t* invokeId, int reason, ByteBuffer* response) { int rejectType = 0; int rejectReason = 0; switch (reason) { case MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE: rejectType = MMS_REJECT_CONFIRMED_REQUEST; rejectReason = MMS_REJECT_CONFIRMED_REQUEST_UNRECOGNIZED_SERVICE; break; case MMS_ERROR_REJECT_UNKNOWN_PDU_TYPE: rejectType = MMS_REJECT_PDU_ERROR; rejectReason = MMS_REJECT_PDU_ERROR_UNKNOWN_PDU_TYPE; break; case MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT: rejectType = MMS_REJECT_CONFIRMED_REQUEST; rejectReason = MMS_REJECT_CONFIRMED_REQUEST_INVALID_ARGUMENT; break; case MMS_ERROR_REJECT_INVALID_PDU: rejectType = MMS_REJECT_PDU_ERROR; rejectReason = MMS_REJECT_PDU_ERROR_INVALID_PDU; break; default: rejectType = MMS_REJECT_CONFIRMED_REQUEST; rejectReason = MMS_REJECT_CONFIRMED_REQUEST_OTHER; } mmsMsg_encodeMmsRejectPdu(invokeId, rejectType, rejectReason, response); } /********************************************************************************************** * MMS General service handling functions *********************************************************************************************/ static void handleConfirmedRequestPdu( MmsServerConnection self, uint8_t* buffer, int bufPos, int maxBufPos, ByteBuffer* response) { uint32_t invokeId = 0; while (bufPos < maxBufPos) { uint8_t tag = buffer[bufPos++]; int length; bool extendedTag = false; if ((tag & 0x1f) == 0x1f) { extendedTag = true; tag = buffer[bufPos++]; } bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos); if (bufPos < 0) { mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); return; } if (bufPos + length > maxBufPos) { mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response); return; } if (extendedTag) { switch (tag) { #if (MMS_OBTAIN_FILE_SERVICE == 1) #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x2e: /* obtain-file */ if (self->server->fileServiceEnabled) mmsServer_handleObtainFileRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x2e: /* obtain-file */ mmsServer_handleObtainFileRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #endif /* MMS_OBTAIN_FILE_SERVICE == 1 */ #if (MMS_JOURNAL_SERVICE == 1) #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x41: /* read-journal */ if (self->server->journalServiceEnabled) mmsServer_handleReadJournalRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x41: /* read-journal */ mmsServer_handleReadJournalRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #endif /* (MMS_JOURNAL_SERVICE == 1) */ #if (MMS_FILE_SERVICE == 1) #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x48: /* file-open-request */ if (self->server->fileServiceEnabled) mmsServer_handleFileOpenRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x48: /* file-open-request */ mmsServer_handleFileOpenRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x49: /* file-read-request */ if (self->server->fileServiceEnabled) mmsServer_handleFileReadRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x49: /* file-read-request */ mmsServer_handleFileReadRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x4a: /* file-close-request */ if (self->server->fileServiceEnabled) mmsServer_handleFileCloseRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x4a: /* file-close-request */ mmsServer_handleFileCloseRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x4b: /* file-rename-request */ if (self->server->fileServiceEnabled) mmsServer_handleFileRenameRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x4b: /* file-rename-request */ mmsServer_handleFileRenameRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x4c: /* file-delete-request */ if (self->server->fileServiceEnabled) mmsServer_handleFileDeleteRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x4c: /* file-delete-request */ mmsServer_handleFileDeleteRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0x4d: /* file-directory-request */ if (self->server->fileServiceEnabled) mmsServer_handleFileDirectoryRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0x4d: /* file-directory-request */ mmsServer_handleFileDirectoryRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #endif /* MMS_FILE_SERVICE == 1 */ default: mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); return; break; } } else { switch (tag) { case 0x02: /* invoke Id */ invokeId = BerDecoder_decodeUint32(buffer, length, bufPos); if (DEBUG_MMS_SERVER) printf("MMS_SERVER: received request with invokeId: %i\n", invokeId); self->lastInvokeId = invokeId; break; #if (MMS_STATUS_SERVICE == 1) case 0x80: /* status-request */ mmsServer_handleStatusRequest(self, buffer, bufPos, invokeId, response); break; #endif /* MMS_STATUS_SERVICE == 1 */ #if (MMS_GET_NAME_LIST == 1) case 0xa1: /* get-name-list-request */ mmsServer_handleGetNameListRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (MMS_GET_NAME_LIST == 1) */ #if (MMS_IDENTIFY_SERVICE == 1) case 0x82: /* identify */ mmsServer_handleIdentifyRequest(self, invokeId, response); break; #endif /* MMS_IDENTIFY_SERVICE == 1 */ case 0xa4: /* read-request */ mmsServer_handleReadRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #if (MMS_WRITE_SERVICE == 1) case 0xa5: /* write-request */ mmsServer_handleWriteRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (MMS_WRITE_SERVICE == 1) */ #if (MMS_GET_VARIABLE_ACCESS_ATTRIBUTES == 1) case 0xa6: /* get-variable-access-attributes-request */ mmsServer_handleGetVariableAccessAttributesRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* MMS_GET_VARIABLE_ACCESS_ATTRIBUTES == 1 */ #if (MMS_DYNAMIC_DATA_SETS == 1) #if (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) case 0xab: /* define-named-variable-list */ if (self->server->dynamicVariableListServiceEnabled) mmsServer_handleDefineNamedVariableListRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; case 0xad: /* delete-named-variable-list-request */ if (self->server->dynamicVariableListServiceEnabled) mmsServer_handleDeleteNamedVariableListRequest(self, buffer, bufPos, bufPos + length, invokeId, response); else mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); break; #else case 0xab: /* define-named-variable-list */ mmsServer_handleDefineNamedVariableListRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; case 0xad: /* delete-named-variable-list-request */ mmsServer_handleDeleteNamedVariableListRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (CONFIG_MMS_SERVER_CONFIG_SERVICES_AT_RUNTIME == 1) */ #endif /* (MMS_DYNAMIC_DATA_SETS == 1) */ #if (MMS_GET_DATA_SET_ATTRIBUTES == 1) case 0xac: /* get-named-variable-list-attributes-request */ mmsServer_handleGetNamedVariableListAttributesRequest(self, buffer, bufPos, bufPos + length, invokeId, response); break; #endif /* (MMS_GET_DATA_SET_ATTRIBUTES == 1) */ default: mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); return; break; } } bufPos += length; } } #if (MMS_OBTAIN_FILE_SERVICE == 1) static void handleConfirmedErrorPdu( MmsServerConnection self, uint8_t* buffer, int bufPos, int maxBufPos, ByteBuffer* response) { uint32_t invokeId; MmsServiceError serviceError; if (mmsMsg_parseConfirmedErrorPDU(buffer, bufPos, maxBufPos, &invokeId, &serviceError)) { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: Handle confirmed error PDU: invokeID: %i\n", invokeId); /* check if message is related to an existing file upload task */ int i; for (i = 0; i < CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS; i++) { if (self->server->fileUploadTasks[i].state != MMS_FILE_UPLOAD_STATE_NOT_USED) { if (self->server->fileUploadTasks[i].lastRequestInvokeId == invokeId) { self->server->fileUploadTasks[i].state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE; return; } } } } else { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: error parsing confirmed error PDU\n"); } } static MmsObtainFileTask getUploadTaskByInvokeId(MmsServer mmsServer, uint32_t invokeId) { int i; for (i = 0; i < CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS; i++) { if (mmsServer->fileUploadTasks[i].lastRequestInvokeId == invokeId) return &(mmsServer->fileUploadTasks[i]); } return NULL; } static void mmsFileReadHandler(uint32_t invokeId, void* parameter, MmsError mmsError, uint8_t* buffer, uint32_t bytesReceived, bool moreFollows) { MmsObtainFileTask task = (MmsObtainFileTask) parameter; if (DEBUG_MMS_SERVER) printf("MMS_SERVER: file %i received %i bytes\n", task->frmsId, bytesReceived); FileSystem_writeFile(task->fileHandle, buffer, bytesReceived); } static void handleConfirmedResponsePdu( MmsServerConnection self, uint8_t* buffer, int bufPos, int maxBufPos, ByteBuffer* response) { uint32_t invokeId = 0; while (bufPos < maxBufPos) { int startBufPos = bufPos; uint8_t tag = buffer[bufPos++]; int length; bool extendedTag = false; if ((tag & 0x1f) == 0x1f) { extendedTag = true; tag = buffer[bufPos++]; } bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos); if (bufPos < 0) { mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); return; } if (extendedTag) { switch (tag) { #if (MMS_FILE_SERVICE == 1) case 0x48: /* file-open-response */ if (DEBUG_MMS_SERVER) printf("MMS_SERVER: received file-open-response\n"); { MmsObtainFileTask fileTask = getUploadTaskByInvokeId(self->server, invokeId); if (fileTask != NULL) { int32_t frmsId; if (mmsMsg_parseFileOpenResponse(buffer, startBufPos, maxBufPos, &frmsId, NULL, NULL)) { fileTask->frmsId = frmsId; fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_FILE_READ; } else { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: error parsing file-open-response\n"); fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE; } } else { /* ignore */ if (DEBUG_MMS_SERVER) printf("MMS_SERVER: unexpected file-open-response\n"); } } break; case 0x49: /* file-read-response */ { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: received file-read-response\n"); MmsObtainFileTask fileTask = getUploadTaskByInvokeId(self->server, invokeId); if (fileTask != NULL) { bool moreFollows; if (mmsMsg_parseFileReadResponse(buffer, startBufPos, maxBufPos, invokeId, fileTask->frmsId, &moreFollows, mmsFileReadHandler, (void*) fileTask)) { if (moreFollows) { fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_FILE_READ; } else { fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_FILE_CLOSE; } } else { fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE; if (DEBUG_MMS_SERVER) printf("MMS_SERVER: error parsing file-read-response\n"); } } else { /* ignore */ if (DEBUG_MMS_SERVER) printf("MMS_SERVER: unexpected file-read-response\n"); } } break; case 0x4a: /* file-close-response */ { if (DEBUG_MMS_SERVER) printf("MMS_SERVER: received file-close-response\n"); MmsObtainFileTask fileTask = getUploadTaskByInvokeId(self->server, invokeId); if (fileTask != NULL) { FileSystem_closeFile(fileTask->fileHandle); fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_RESPONSE; } else { /* ignore */ if (DEBUG_MMS_SERVER) printf("MMS_SERVER: unexpected file-close-response\n"); } } break; #endif /* MMS_FILE_SERVICE == 1 */ default: mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); return; break; } } else { switch (tag) { case 0x02: /* invoke Id */ invokeId = BerDecoder_decodeUint32(buffer, length, bufPos); if (DEBUG_MMS_SERVER) printf("MMS_SERVER: received request with invokeId: %i\n", invokeId); self->lastInvokeId = invokeId; break; default: mmsMsg_createMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response); return; break; } } bufPos += length; } } /* handleConfirmedResponsePdu */ #endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */ static inline void MmsServerConnection_parseMessage(MmsServerConnection self, ByteBuffer* message, ByteBuffer* response) { uint8_t* buffer = message->buffer; if (message->size < 2) goto parsing_error; int bufPos = 0; uint8_t pduType = buffer[bufPos++]; int pduLength; bufPos = BerDecoder_decodeLength(buffer, &pduLength, bufPos, message->size); if (bufPos < 0) goto parsing_error; if (DEBUG_MMS_SERVER) printf("MMS_SERVER: recvd MMS-PDU type: %02x size: %i\n", pduType, pduLength); switch (pduType) { case 0xa8: /* Initiate request PDU */ mmsServer_handleInitiateRequest(self, buffer, bufPos, bufPos + pduLength, response); break; case 0xa0: /* Confirmed request PDU */ handleConfirmedRequestPdu(self, buffer, bufPos, bufPos + pduLength, response); break; #if (MMS_OBTAIN_FILE_SERVICE == 1) case 0xa1: /* Confirmed response PDU */ handleConfirmedResponsePdu(self, buffer, bufPos, bufPos + pduLength, response); break; case 0xa2: /* Confirmed error PDU */ handleConfirmedErrorPdu(self, buffer, 0, bufPos + pduLength, response); break; #endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */ case 0x8b: /* Conclude request PDU */ mmsServer_writeConcludeResponsePdu(response); break; case 0xa4: /* Reject PDU - silently ignore */ if (DEBUG_MMS_SERVER) printf("MMS_SERVER: received reject PDU!\n"); break; default: mmsMsg_createMmsRejectPdu(NULL, MMS_ERROR_REJECT_UNKNOWN_PDU_TYPE, response); break; } return; parsing_error: if (DEBUG_MMS_SERVER) printf("MMS_SERVER: error parsing message\n"); return; } static void /* will be called by IsoConnection */ messageReceived(void* parameter, ByteBuffer* message, ByteBuffer* response) { MmsServerConnection self = (MmsServerConnection) parameter; MmsServerConnection_parseMessage(self, message, response); } /********************************************************************************************** * MMS server connection public API functions *********************************************************************************************/ MmsServerConnection MmsServerConnection_init(MmsServerConnection connection, MmsServer server, IsoConnection isoCon) { MmsServerConnection self; if (connection == NULL) self = (MmsServerConnection) GLOBAL_CALLOC(1, sizeof(struct sMmsServerConnection)); else self = connection; self->maxServOutstandingCalled = 0; self->maxServOutstandingCalling = 0; self->maxPduSize = CONFIG_MMS_MAXIMUM_PDU_SIZE; self->dataStructureNestingLevel = 0; self->server = server; self->isoConnection = isoCon; #if (MMS_DYNAMIC_DATA_SETS == 1) self->namedVariableLists = LinkedList_create(); #endif #if (MMS_OBTAIN_FILE_SERVICE == 1) self->lastRequestInvokeId = 0; #endif IsoConnection_installListener(isoCon, messageReceived, (void*) self); return self; } void MmsServerConnection_destroy(MmsServerConnection self) { #if (MMS_FILE_SERVICE == 1) int frsmIndex = 0; for (frsmIndex = 0; frsmIndex < CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION; frsmIndex++) if (self->frsms[frsmIndex].fileHandle != NULL) FileSystem_closeFile(self->frsms[frsmIndex].fileHandle); #endif #if (MMS_DYNAMIC_DATA_SETS == 1) LinkedList_destroyDeep(self->namedVariableLists, (LinkedListValueDeleteFunction) MmsNamedVariableList_destroy); #endif GLOBAL_FREEMEM(self); } int MmsServerConnection_getMaxMmsPduSize(MmsServerConnection self) { return self->maxPduSize; } void MmsServerConnection_sendMessage(MmsServerConnection self, ByteBuffer* message, bool handlerMode) { IsoConnection_sendMessage(self->isoConnection, message, false); } #if (MMS_DYNAMIC_DATA_SETS == 1) bool MmsServerConnection_addNamedVariableList(MmsServerConnection self, MmsNamedVariableList variableList) { /* TODO check if operation is allowed! */ LinkedList_add(self->namedVariableLists, variableList); return true; } void MmsServerConnection_deleteNamedVariableList(MmsServerConnection self, char* listName) { mmsServer_deleteVariableList(self->namedVariableLists, listName); } MmsNamedVariableList MmsServerConnection_getNamedVariableList(MmsServerConnection self, const char* variableListName) { return mmsServer_getNamedVariableListWithName(self->namedVariableLists, variableListName); } #endif /* (MMS_DYNAMIC_DATA_SETS == 1) */ char* MmsServerConnection_getClientAddress(MmsServerConnection self) { return IsoConnection_getPeerAddress(self->isoConnection); } IsoConnection MmsServerConnection_getIsoConnection(MmsServerConnection self) { return self->isoConnection; } #if (MMS_DYNAMIC_DATA_SETS == 1) LinkedList MmsServerConnection_getNamedVariableLists(MmsServerConnection self) { return self->namedVariableLists; } #endif /* (MMS_DYNAMIC_DATA_SETS == 1) */ uint32_t MmsServerConnection_getLastInvokeId(MmsServerConnection self) { return self->lastInvokeId; } #if (MMS_OBTAIN_FILE_SERVICE == 1) uint32_t MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self) { self->lastRequestInvokeId++; return self->lastRequestInvokeId; } #endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */ const char* MmsServerConnection_getFilesystemBasepath(MmsServerConnection self) { #if (CONFIG_SET_FILESTORE_BASEPATH_AT_RUNTIME == 1) if (self->server->filestoreBasepath != NULL) return self->server->filestoreBasepath; else return CONFIG_VIRTUAL_FILESTORE_BASEPATH; #else return CONFIG_VIRTUAL_FILESTORE_BASEPATH; #endif }