- implemented server side obtain file procedure
This commit is contained in:
parent
4d5a9e27a1
commit
d15e2c73b1
20 changed files with 1097 additions and 82 deletions
|
@ -179,6 +179,9 @@
|
||||||
/* Maximum number of the members in a data set (named variable list) */
|
/* Maximum number of the members in a data set (named variable list) */
|
||||||
#define CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS 100
|
#define CONFIG_MMS_MAX_NUMBER_OF_DATA_SET_MEMBERS 100
|
||||||
|
|
||||||
|
/* maximum number of contemporary file upload tasks (obtainFile) per server instance */
|
||||||
|
#define CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS 5
|
||||||
|
|
||||||
/* Definition of supported services */
|
/* Definition of supported services */
|
||||||
#define MMS_DEFAULT_PROFILE 1
|
#define MMS_DEFAULT_PROFILE 1
|
||||||
|
|
||||||
|
@ -194,6 +197,7 @@
|
||||||
#define MMS_STATUS_SERVICE 1
|
#define MMS_STATUS_SERVICE 1
|
||||||
#define MMS_IDENTIFY_SERVICE 1
|
#define MMS_IDENTIFY_SERVICE 1
|
||||||
#define MMS_FILE_SERVICE 1
|
#define MMS_FILE_SERVICE 1
|
||||||
|
#define MMS_OBTAIN_FILE_SERVICE 1
|
||||||
#endif /* MMS_DEFAULT_PROFILE */
|
#endif /* MMS_DEFAULT_PROFILE */
|
||||||
|
|
||||||
#if (MMS_WRITE_SERVICE != 1)
|
#if (MMS_WRITE_SERVICE != 1)
|
||||||
|
@ -216,7 +220,7 @@
|
||||||
/* use short FC defines as in old API */
|
/* use short FC defines as in old API */
|
||||||
#define CONFIG_PROVIDE_OLD_FC_DEFINES 0
|
#define CONFIG_PROVIDE_OLD_FC_DEFINES 0
|
||||||
|
|
||||||
/* Support user acccess to raw messages */
|
/* Support user access to raw messages */
|
||||||
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 1
|
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 1
|
||||||
|
|
||||||
#endif /* STACK_CONFIG_H_ */
|
#endif /* STACK_CONFIG_H_ */
|
||||||
|
|
|
@ -186,6 +186,7 @@
|
||||||
#define MMS_STATUS_SERVICE 1
|
#define MMS_STATUS_SERVICE 1
|
||||||
#define MMS_IDENTIFY_SERVICE 1
|
#define MMS_IDENTIFY_SERVICE 1
|
||||||
#define MMS_FILE_SERVICE 1
|
#define MMS_FILE_SERVICE 1
|
||||||
|
#define MMS_OBTAIN_FILE_SERVICE 1
|
||||||
#endif /* MMS_DEFAULT_PROFILE */
|
#endif /* MMS_DEFAULT_PROFILE */
|
||||||
|
|
||||||
#if (MMS_WRITE_SERVICE != 1)
|
#if (MMS_WRITE_SERVICE != 1)
|
||||||
|
|
|
@ -35,6 +35,7 @@ DataAttribute* toDataAttribute(ModelNode * MN)
|
||||||
%include "iec61850_server.h"
|
%include "iec61850_server.h"
|
||||||
%include "iec61850_dynamic_model.h"
|
%include "iec61850_dynamic_model.h"
|
||||||
%include "iec61850_cdc.h"
|
%include "iec61850_cdc.h"
|
||||||
|
%include "linked_list.h
|
||||||
ModelNode* toModelNode(LogicalNode *);
|
ModelNode* toModelNode(LogicalNode *);
|
||||||
ModelNode* toModelNode(DataObject *);
|
ModelNode* toModelNode(DataObject *);
|
||||||
DataAttribute* toDataAttribute(DataObject *);
|
DataAttribute* toDataAttribute(DataObject *);
|
||||||
|
|
|
@ -3021,6 +3021,9 @@ processPeriodicTasks(MmsMapping* self)
|
||||||
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
||||||
Logging_processIntegrityLogs(self, currentTimeInMs);
|
Logging_processIntegrityLogs(self, currentTimeInMs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* handle low priority MMS backgound tasks (like file upload...) */
|
||||||
|
MmsServer_handleBackgroundTasks(self->mmsServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -661,9 +661,13 @@ typedef void
|
||||||
typedef void
|
typedef void
|
||||||
(*MmsFileReadHandler) (void* parameter, int32_t frsmId, uint8_t* buffer, uint32_t bytesReceived);
|
(*MmsFileReadHandler) (void* parameter, int32_t frsmId, uint8_t* buffer, uint32_t bytesReceived);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief open a file for read
|
* \brief open a file for read
|
||||||
*
|
*
|
||||||
|
* \param self MmsConnection instance to operate on
|
||||||
|
* \param mmsError user provided variable to store error code
|
||||||
|
*
|
||||||
* \return the FRSM ID (file read state machine) handle of the opened file
|
* \return the FRSM ID (file read state machine) handle of the opened file
|
||||||
*/
|
*/
|
||||||
int32_t
|
int32_t
|
||||||
|
|
|
@ -124,6 +124,17 @@ typedef MmsError (*MmsNamedVariableListChangedHandler)(void* parameter, bool cre
|
||||||
void
|
void
|
||||||
MmsServer_installVariableListChangedHandler(MmsServer self, MmsNamedVariableListChangedHandler handler, void* parameter);
|
MmsServer_installVariableListChangedHandler(MmsServer self, MmsNamedVariableListChangedHandler handler, void* parameter);
|
||||||
|
|
||||||
|
|
||||||
|
typedef bool (*MmsObtainFileHandler)(void* parameter, MmsServerConnection connection, const char* sourceFilename, const char* destinationFilename);
|
||||||
|
|
||||||
|
void
|
||||||
|
MmsServer_installObtainFileHandler(MmsServer self, MmsObtainFileHandler handler, void* parameter);
|
||||||
|
|
||||||
|
typedef void (*MmsGetFileCompleteHandler)(void* parameter, MmsServerConnection connection, const char* destinationFilename);
|
||||||
|
|
||||||
|
void
|
||||||
|
MmsServer_installGetFileCompleteHandler(MmsServer self, MmsGetFileCompleteHandler handler, void* parameter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief lock the cached server data model
|
* \brief lock the cached server data model
|
||||||
*
|
*
|
||||||
|
@ -209,6 +220,14 @@ MmsServer_waitReady(MmsServer self, unsigned int timeoutMs);
|
||||||
void
|
void
|
||||||
MmsServer_handleIncomingMessages(MmsServer self);
|
MmsServer_handleIncomingMessages(MmsServer self);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Handle MmsServer background task
|
||||||
|
*
|
||||||
|
* \param self the MmsServer instance to operate on
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
MmsServer_handleBackgroundTasks(MmsServer self);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Stop the server (for non-threaded operation mode)
|
* \brief Stop the server (for non-threaded operation mode)
|
||||||
*
|
*
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
|
|
||||||
#include "hal_thread.h"
|
#include "hal_thread.h"
|
||||||
|
|
||||||
|
#include "mms_common_internal.h"
|
||||||
|
|
||||||
#ifndef CONFIG_MMS_RAW_MESSAGE_LOGGING
|
#ifndef CONFIG_MMS_RAW_MESSAGE_LOGGING
|
||||||
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 0
|
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -96,6 +98,11 @@ struct sMmsConnection {
|
||||||
|
|
||||||
/* state of an active connection conclude/release process */
|
/* state of an active connection conclude/release process */
|
||||||
int concludeState;
|
int concludeState;
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
int32_t nextFrsmId;
|
||||||
|
MmsFileReadStateMachine frsms[CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -231,15 +238,9 @@ mmsClient_parseStatusResponse(MmsConnection self, int* vmdLogicalStatus, int* vm
|
||||||
void
|
void
|
||||||
mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const char* fileName, uint32_t initialPosition);
|
mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const char* fileName, uint32_t initialPosition);
|
||||||
|
|
||||||
bool
|
|
||||||
mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* fileSize, uint64_t* lastModified);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mmsClient_createFileReadRequest(uint32_t invokeId, ByteBuffer* request, int32_t frsmId);
|
mmsClient_createFileReadRequest(uint32_t invokeId, ByteBuffer* request, int32_t frsmId);
|
||||||
|
|
||||||
bool
|
|
||||||
mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreFollows, MmsFileReadHandler handler, void* handlerParameter);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mmsClient_createFileCloseRequest(uint32_t invokeId, ByteBuffer* request, int32_t frsmId);
|
mmsClient_createFileCloseRequest(uint32_t invokeId, ByteBuffer* request, int32_t frsmId);
|
||||||
|
|
||||||
|
@ -280,4 +281,25 @@ mmsClient_createReadJournalRequestStartAfter(uint32_t invokeId, ByteBuffer* requ
|
||||||
bool
|
bool
|
||||||
mmsClient_parseReadJournalResponse(MmsConnection self, bool* moreFollows, LinkedList* result);
|
mmsClient_parseReadJournalResponse(MmsConnection self, bool* moreFollows, LinkedList* result);
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsClient_handleFileOpenRequest(MmsConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId, ByteBuffer* response);
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsClient_handleFileReadRequest(
|
||||||
|
MmsConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId,
|
||||||
|
ByteBuffer* response);
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsClient_handleFileReadRequest(
|
||||||
|
MmsConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId,
|
||||||
|
ByteBuffer* response);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* MMS_MSG_INTERNAL_H_ */
|
#endif /* MMS_MSG_INTERNAL_H_ */
|
||||||
|
|
|
@ -27,6 +27,50 @@
|
||||||
#include "mms_value.h"
|
#include "mms_value.h"
|
||||||
#include "MmsPdu.h"
|
#include "MmsPdu.h"
|
||||||
#include "conversions.h"
|
#include "conversions.h"
|
||||||
|
#include "byte_buffer.h"
|
||||||
|
|
||||||
|
#if (MMS_FILE_SERVICE == 1)
|
||||||
|
|
||||||
|
#ifndef CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION
|
||||||
|
#define CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "hal_filesystem.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t frsmId;
|
||||||
|
uint32_t readPosition;
|
||||||
|
uint32_t fileSize;
|
||||||
|
FileHandle fileHandle;
|
||||||
|
} MmsFileReadStateMachine;
|
||||||
|
|
||||||
|
//TODO already defined in public API mms_connection.h
|
||||||
|
typedef void
|
||||||
|
(*MmsFileReadHandler) (void* parameter, int32_t frsmId, uint8_t* buffer, uint32_t bytesReceived);
|
||||||
|
|
||||||
|
bool
|
||||||
|
mmsMsg_parseFileOpenResponse(uint8_t* buffer, int bufPos, int maxBufPos, int32_t* frsmId, uint32_t* fileSize, uint64_t* lastModified);
|
||||||
|
|
||||||
|
bool
|
||||||
|
mmsMsg_parseFileReadResponse(uint8_t* buffer, int bufPos, int maxBufPos, int32_t frsmId, bool* moreFollows, MmsFileReadHandler handler, void* handlerParameter);
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsMsg_createFileReadResponse(int maxPduSize, uint32_t invokeId, ByteBuffer* response, MmsFileReadStateMachine* frsm);
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsMsg_createFileCloseResponse(uint32_t invokeId, ByteBuffer* response);
|
||||||
|
|
||||||
|
#endif /* (MMS_FILE_SERVICE == 1) */
|
||||||
|
|
||||||
|
typedef struct sMmsServiceError
|
||||||
|
{
|
||||||
|
int errorClass;
|
||||||
|
int errorCode;
|
||||||
|
} MmsServiceError;
|
||||||
|
|
||||||
|
int
|
||||||
|
mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, MmsServiceError* serviceError);
|
||||||
|
|
||||||
|
|
||||||
MmsValue*
|
MmsValue*
|
||||||
mmsMsg_parseDataElement(Data_t* dataElement);
|
mmsMsg_parseDataElement(Data_t* dataElement);
|
||||||
|
|
|
@ -98,6 +98,9 @@ MmsServerConnection_sendWriteResponse(MmsServerConnection self, uint32_t invokeI
|
||||||
uint32_t
|
uint32_t
|
||||||
MmsServerConnection_getLastInvokeId(MmsServerConnection self);
|
MmsServerConnection_getLastInvokeId(MmsServerConnection self);
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self);
|
||||||
|
|
||||||
#endif /* MMS_SERVER_CONNECTION_H_ */
|
#endif /* MMS_SERVER_CONNECTION_H_ */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#include "libiec61850_platform_includes.h"
|
#include "libiec61850_platform_includes.h"
|
||||||
|
|
||||||
#include <MmsPdu.h>
|
#include "MmsPdu.h"
|
||||||
#include "mms_common.h"
|
#include "mms_common.h"
|
||||||
#include "mms_indication.h"
|
#include "mms_indication.h"
|
||||||
#include "mms_server_connection.h"
|
#include "mms_server_connection.h"
|
||||||
|
@ -44,6 +44,11 @@
|
||||||
#include "ber_encoder.h"
|
#include "ber_encoder.h"
|
||||||
#include "ber_decode.h"
|
#include "ber_decode.h"
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
#include "hal_filesystem.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef DEBUG_MMS_SERVER
|
#ifndef DEBUG_MMS_SERVER
|
||||||
#define DEBUG_MMS_SERVER 0
|
#define DEBUG_MMS_SERVER 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,6 +65,42 @@
|
||||||
#define MMS_FILE_SERVICE 1
|
#define MMS_FILE_SERVICE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS
|
||||||
|
#define CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_NOT_USED 0
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_READY 1
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_FILE_OPEN_SENT 2
|
||||||
|
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_SEND_FILE_READ 3
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_FILE_READ_SENT 4
|
||||||
|
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_SEND_FILE_CLOSE 5
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_FILE_CLOSE_SENT 6
|
||||||
|
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE 8
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_DESTINATION 9
|
||||||
|
#define MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_RESPONSE 10
|
||||||
|
|
||||||
|
typedef struct sMmsObtainFileTask* MmsObtainFileTask;
|
||||||
|
|
||||||
|
struct sMmsObtainFileTask {
|
||||||
|
MmsServerConnection connection;
|
||||||
|
uint32_t lastRequestInvokeId;
|
||||||
|
uint32_t obtainFileRequestInvokeId;
|
||||||
|
FileHandle fileHandle;
|
||||||
|
char destinationFilename[256];
|
||||||
|
uint64_t nextTimeout;
|
||||||
|
int32_t frmsId;
|
||||||
|
int state;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
|
|
||||||
struct sMmsServer {
|
struct sMmsServer {
|
||||||
IsoServer isoServer;
|
IsoServer isoServer;
|
||||||
MmsDevice* device;
|
MmsDevice* device;
|
||||||
|
@ -83,7 +124,10 @@ struct sMmsServer {
|
||||||
Map valueCaches;
|
Map valueCaches;
|
||||||
bool isLocked;
|
bool isLocked;
|
||||||
|
|
||||||
ByteBuffer* reportBuffer; /* global buffer for encoding reports */
|
ByteBuffer* transmitBuffer; /* global buffer for encoding reports, delayed responses... */
|
||||||
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
||||||
|
Semaphore transmitBufferMutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
||||||
Semaphore modelMutex;
|
Semaphore modelMutex;
|
||||||
|
@ -101,24 +145,18 @@ struct sMmsServer {
|
||||||
char* modelName;
|
char* modelName;
|
||||||
char* revision;
|
char* revision;
|
||||||
#endif /* MMS_IDENTIFY_SERVICE == 1 */
|
#endif /* MMS_IDENTIFY_SERVICE == 1 */
|
||||||
};
|
|
||||||
|
|
||||||
#if (MMS_FILE_SERVICE == 1)
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
MmsObtainFileHandler obtainFileHandler;
|
||||||
|
void* obtainFileHandlerParameter;
|
||||||
|
|
||||||
#ifndef CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION
|
MmsGetFileCompleteHandler getFileCompleteHandler;
|
||||||
#define CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION 5
|
void* getFileCompleteHandlerParameter;
|
||||||
|
|
||||||
|
struct sMmsObtainFileTask fileUploadTasks[CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "hal_filesystem.h"
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t frsmId;
|
|
||||||
uint32_t readPosition;
|
|
||||||
uint32_t fileSize;
|
|
||||||
FileHandle fileHandle;
|
|
||||||
} MmsFileReadStateMachine;
|
|
||||||
|
|
||||||
#endif /* (MMS_FILE_SERVICE == 1) */
|
|
||||||
|
|
||||||
struct sMmsServerConnection {
|
struct sMmsServerConnection {
|
||||||
int maxServOutstandingCalling;
|
int maxServOutstandingCalling;
|
||||||
|
@ -129,6 +167,10 @@ struct sMmsServerConnection {
|
||||||
MmsServer server;
|
MmsServer server;
|
||||||
uint32_t lastInvokeId;
|
uint32_t lastInvokeId;
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
uint32_t lastRequestInvokeId; /* only used by obtainFile service */
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (MMS_DYNAMIC_DATA_SETS == 1)
|
#if (MMS_DYNAMIC_DATA_SETS == 1)
|
||||||
LinkedList /*<MmsNamedVariableList>*/namedVariableLists; /* aa-specific named variable lists */
|
LinkedList /*<MmsNamedVariableList>*/namedVariableLists; /* aa-specific named variable lists */
|
||||||
#endif
|
#endif
|
||||||
|
@ -137,13 +179,25 @@ struct sMmsServerConnection {
|
||||||
int32_t nextFrsmId;
|
int32_t nextFrsmId;
|
||||||
MmsFileReadStateMachine frsms[CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION];
|
MmsFileReadStateMachine frsms[CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
MmsObtainFileTask
|
||||||
|
MmsServer_getObtainFileTask(MmsServer self);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ByteBuffer*
|
||||||
|
MmsServer_reserveTransmitBuffer(MmsServer self);
|
||||||
|
|
||||||
|
void
|
||||||
|
MmsServer_releaseTransmitBuffer(MmsServer self);
|
||||||
|
|
||||||
/* write_out function required for ASN.1 encoding */
|
/* write_out function required for ASN.1 encoding */
|
||||||
int
|
int
|
||||||
mmsServer_write_out(const void *buffer, size_t size, void *app_key);
|
mmsServer_write_out(const void *buffer, size_t size, void *app_key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection,
|
mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection,
|
||||||
uint8_t* buffer, int bufPos, int maxBufPos,
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
@ -275,6 +329,13 @@ mmsServer_handleFileCloseRequest(
|
||||||
uint32_t invokeId,
|
uint32_t invokeId,
|
||||||
ByteBuffer* response);
|
ByteBuffer* response);
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsServer_handleObtainFileRequest(
|
||||||
|
MmsServerConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId,
|
||||||
|
ByteBuffer* response);
|
||||||
|
|
||||||
int
|
int
|
||||||
mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess);
|
mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess);
|
||||||
|
|
||||||
|
|
|
@ -327,7 +327,7 @@ sendRequestAndWaitForResponse(MmsConnection self, uint32_t invokeId, ByteBuffer*
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("TIMEOUT for request %u: \n", invokeId);
|
printf("MMS_CLIENT: TIMEOUT for request %u: \n", invokeId);
|
||||||
self->lastResponseError = MMS_ERROR_SERVICE_TIMEOUT;
|
self->lastResponseError = MMS_ERROR_SERVICE_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,12 +372,6 @@ waitUntilLastResponseHasBeenProcessed(MmsConnection self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct sMmsServiceError
|
|
||||||
{
|
|
||||||
int errorClass;
|
|
||||||
int errorCode;
|
|
||||||
} MmsServiceError;
|
|
||||||
|
|
||||||
static MmsError
|
static MmsError
|
||||||
convertServiceErrorToMmsError(MmsServiceError serviceError)
|
convertServiceErrorToMmsError(MmsServiceError serviceError)
|
||||||
{
|
{
|
||||||
|
@ -519,12 +513,9 @@ parseServiceError(uint8_t* buffer, int bufPos, int maxLength, MmsServiceError* e
|
||||||
return bufPos;
|
return bufPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
int
|
||||||
parseConfirmedErrorPDU(ByteBuffer* message, uint32_t* invokeId, MmsServiceError* serviceError)
|
mmsMsg_parseConfirmedErrorPDU(uint8_t* buffer, int bufPos, int maxBufPos, uint32_t* invokeId, MmsServiceError* serviceError)
|
||||||
{
|
{
|
||||||
uint8_t* buffer = message->buffer;
|
|
||||||
int maxBufPos = message->size;
|
|
||||||
int bufPos = 0;
|
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
uint8_t tag = buffer[bufPos++];
|
uint8_t tag = buffer[bufPos++];
|
||||||
|
@ -675,7 +666,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
|
||||||
uint32_t invokeId;
|
uint32_t invokeId;
|
||||||
MmsServiceError serviceError = {0, 0};
|
MmsServiceError serviceError = {0, 0};
|
||||||
|
|
||||||
if (parseConfirmedErrorPDU(payload, &invokeId, &serviceError) < 0) {
|
if (mmsMsg_parseConfirmedErrorPDU(payload->buffer, 0, payload->size, &invokeId, &serviceError) < 0) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("MMS_CLIENT: Error parsing confirmedErrorPDU!\n");
|
printf("MMS_CLIENT: Error parsing confirmedErrorPDU!\n");
|
||||||
}
|
}
|
||||||
|
@ -742,6 +733,124 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
|
||||||
else
|
else
|
||||||
goto exit_with_error;
|
goto exit_with_error;
|
||||||
}
|
}
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
else if (tag == 0xa0) {
|
||||||
|
|
||||||
|
printf("MMS_CLIENT: received confirmed request PDU (size=%i)\n", payload->size);
|
||||||
|
|
||||||
|
// TODO handle confirmed request PDU only when obtainFile service is enabled
|
||||||
|
// TODO extract function
|
||||||
|
|
||||||
|
int bufPos = 1;
|
||||||
|
int length;
|
||||||
|
bufPos = BerDecoder_decodeLength(buf, &length, bufPos, payload->size);
|
||||||
|
|
||||||
|
uint32_t invokeId;
|
||||||
|
|
||||||
|
while (bufPos < payload->size) {
|
||||||
|
|
||||||
|
uint8_t tag = buf[bufPos++];
|
||||||
|
|
||||||
|
|
||||||
|
bool extendedTag = false;
|
||||||
|
|
||||||
|
if ((tag & 0x1f) == 0x1f) {
|
||||||
|
extendedTag = true;
|
||||||
|
tag = buf[bufPos++];
|
||||||
|
}
|
||||||
|
|
||||||
|
bufPos = BerDecoder_decodeLength(buf, &length, bufPos, payload->size);
|
||||||
|
|
||||||
|
// printf("tag:%02x len:%i\n", tag, length);
|
||||||
|
|
||||||
|
// if (bufPos < 0) {
|
||||||
|
// mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (extendedTag) {
|
||||||
|
switch(tag) {
|
||||||
|
|
||||||
|
#if (MMS_FILE_SERVICE == 1)
|
||||||
|
case 0x48: /* file-open-request */
|
||||||
|
{
|
||||||
|
printf("MMS_CLIENT: received file-open-request\n");
|
||||||
|
|
||||||
|
ByteBuffer* response = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
|
||||||
|
|
||||||
|
mmsClient_handleFileOpenRequest(self, buf, bufPos, bufPos + length, invokeId, response);
|
||||||
|
|
||||||
|
IsoClientConnection_sendMessage(self->isoClient, response);
|
||||||
|
|
||||||
|
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x49: /* file-read-request */
|
||||||
|
{
|
||||||
|
printf("MMS_CLIENT: received file-read-request\n");
|
||||||
|
|
||||||
|
ByteBuffer* response = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
|
||||||
|
|
||||||
|
mmsClient_handleFileReadRequest(self, buf, bufPos, bufPos + length, invokeId, response);
|
||||||
|
|
||||||
|
IsoClientConnection_sendMessage(self->isoClient, response);
|
||||||
|
|
||||||
|
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x4a: /* file-close-request */
|
||||||
|
{
|
||||||
|
printf("MMS_CLIENT: received file-close-request\n");
|
||||||
|
|
||||||
|
ByteBuffer* response = IsoClientConnection_allocateTransmitBuffer(self->isoClient);
|
||||||
|
|
||||||
|
mmsClient_handleFileCloseRequest(self, buf, bufPos, bufPos + length, invokeId, response);
|
||||||
|
|
||||||
|
IsoClientConnection_sendMessage(self->isoClient, response);
|
||||||
|
|
||||||
|
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* MMS_FILE_SERVICE == 1 */
|
||||||
|
|
||||||
|
default:
|
||||||
|
// mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response);
|
||||||
|
|
||||||
|
printf("MMS_CLIENT: unexpected message from server!\n");
|
||||||
|
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch(tag) {
|
||||||
|
case 0x02: /* invoke Id */
|
||||||
|
invokeId = BerDecoder_decodeUint32(buf, length, bufPos);
|
||||||
|
if (DEBUG_MMS_CLIENT)
|
||||||
|
printf("MMS_CLIENT: received request with invokeId: %i\n", invokeId);
|
||||||
|
self->lastInvokeId = invokeId;
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
default:
|
||||||
|
// mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response);
|
||||||
|
printf("MMS_CLIENT: unexpected message from server!\n");
|
||||||
|
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
||||||
|
|
||||||
|
goto exit_with_error;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bufPos += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
|
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("MMS_CLIENT: LEAVE mmsIsoCallback - OK\n");
|
printf("MMS_CLIENT: LEAVE mmsIsoCallback - OK\n");
|
||||||
|
@ -752,6 +861,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
|
||||||
|
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("received malformed message from server!\n");
|
printf("received malformed message from server!\n");
|
||||||
|
|
||||||
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1811,7 +1921,12 @@ MmsConnection_fileOpen(MmsConnection self, MmsError* mmsError, const char* filen
|
||||||
if (self->lastResponseError != MMS_ERROR_NONE)
|
if (self->lastResponseError != MMS_ERROR_NONE)
|
||||||
*mmsError = self->lastResponseError;
|
*mmsError = self->lastResponseError;
|
||||||
else if (responseMessage != NULL) {
|
else if (responseMessage != NULL) {
|
||||||
if (mmsClient_parseFileOpenResponse(self, &frsmId, fileSize, lastModified) == false)
|
|
||||||
|
uint8_t* buffer = self->lastResponse->buffer;
|
||||||
|
int maxBufPos = self->lastResponse->size;
|
||||||
|
int bufPos = self->lastResponseBufPos;
|
||||||
|
|
||||||
|
if (mmsMsg_parseFileOpenResponse(buffer, bufPos, maxBufPos, &frsmId, fileSize, lastModified) == false)
|
||||||
*mmsError = MMS_ERROR_PARSING_RESPONSE;
|
*mmsError = MMS_ERROR_PARSING_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1890,7 +2005,11 @@ MmsConnection_fileRead(MmsConnection self, MmsError* mmsError, int32_t frsmId, M
|
||||||
if (self->lastResponseError != MMS_ERROR_NONE)
|
if (self->lastResponseError != MMS_ERROR_NONE)
|
||||||
*mmsError = self->lastResponseError;
|
*mmsError = self->lastResponseError;
|
||||||
else if (responseMessage != NULL) {
|
else if (responseMessage != NULL) {
|
||||||
if (mmsClient_parseFileReadResponse(self, frsmId, &moreFollows, handler, handlerParameter) == false)
|
uint8_t* buffer = self->lastResponse->buffer;
|
||||||
|
int maxBufPos = self->lastResponse->size;
|
||||||
|
int bufPos = self->lastResponseBufPos;
|
||||||
|
|
||||||
|
if (mmsMsg_parseFileReadResponse(buffer, bufPos, maxBufPos, frsmId, &moreFollows, handler, handlerParameter) == false)
|
||||||
*mmsError = MMS_ERROR_PARSING_RESPONSE;
|
*mmsError = MMS_ERROR_PARSING_RESPONSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1968,14 +2087,17 @@ MmsConnection_obtainFile(MmsConnection self, MmsError* mmsError, const char* sou
|
||||||
|
|
||||||
uint32_t invokeId = getNextInvokeId(self);
|
uint32_t invokeId = getNextInvokeId(self);
|
||||||
|
|
||||||
|
//TODO enable file service
|
||||||
|
|
||||||
mmsClient_createObtainFileRequest(invokeId, payload, sourceFile, destinationFile);
|
mmsClient_createObtainFileRequest(invokeId, payload, sourceFile, destinationFile);
|
||||||
|
|
||||||
sendRequestAndWaitForResponse(self, invokeId, payload);
|
ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
|
||||||
|
|
||||||
|
|
||||||
if (self->lastResponseError != MMS_ERROR_NONE)
|
if (self->lastResponseError != MMS_ERROR_NONE)
|
||||||
*mmsError = self->lastResponseError;
|
*mmsError = self->lastResponseError;
|
||||||
|
|
||||||
|
/* nothing to do - response contains no data to evaluate */
|
||||||
|
|
||||||
releaseResponse(self);
|
releaseResponse(self);
|
||||||
|
|
||||||
if (self->associationState == MMS_STATE_CLOSED)
|
if (self->associationState == MMS_STATE_CLOSED)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* mms_client_files.c
|
* mms_client_files.c
|
||||||
*
|
*
|
||||||
* Copyright 2013, 2014 Michael Zillgith
|
* Copyright 2013 - 2016 Michael Zillgith
|
||||||
*
|
*
|
||||||
* This file is part of libIEC61850.
|
* This file is part of libIEC61850.
|
||||||
*
|
*
|
||||||
|
@ -32,6 +32,222 @@
|
||||||
#include "ber_decode.h"
|
#include "ber_decode.h"
|
||||||
#include "conversions.h"
|
#include "conversions.h"
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
|
||||||
|
static MmsFileReadStateMachine*
|
||||||
|
getFreeFrsm(MmsConnection connection)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
MmsFileReadStateMachine* freeFrsm = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION; i++) {
|
||||||
|
if (connection->frsms[i].fileHandle == NULL) {
|
||||||
|
freeFrsm = &(connection->frsms[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return freeFrsm;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MmsFileReadStateMachine*
|
||||||
|
getFrsm(MmsConnection connection, int32_t frsmId)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
MmsFileReadStateMachine* frsm = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION; i++) {
|
||||||
|
if (connection->frsms[i].fileHandle != NULL) {
|
||||||
|
if (connection->frsms[i].frsmId == frsmId) {
|
||||||
|
frsm = &(connection->frsms[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return frsm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int32_t
|
||||||
|
getNextFrsmId(MmsConnection connection)
|
||||||
|
{
|
||||||
|
uint32_t nextFrsmId = connection->nextFrsmId;
|
||||||
|
connection->nextFrsmId++;
|
||||||
|
|
||||||
|
return nextFrsmId;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO remove redundancy (with server implementation)
|
||||||
|
static void
|
||||||
|
createExtendedFilename(char* extendedFileName, char* fileName)
|
||||||
|
{
|
||||||
|
strcpy(extendedFileName, CONFIG_VIRTUAL_FILESTORE_BASEPATH);
|
||||||
|
strncat(extendedFileName, fileName, sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO remove redundancy (with server implementation)
|
||||||
|
static FileHandle
|
||||||
|
openFile(char* fileName, bool readWrite)
|
||||||
|
{
|
||||||
|
char extendedFileName[sizeof(CONFIG_VIRTUAL_FILESTORE_BASEPATH) + 256];
|
||||||
|
|
||||||
|
createExtendedFilename(extendedFileName, fileName);
|
||||||
|
|
||||||
|
printf("open file %s\n", extendedFileName);
|
||||||
|
|
||||||
|
return FileSystem_openFile(extendedFileName, readWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO remove redundancy (with server implementation)
|
||||||
|
static bool
|
||||||
|
parseFileName(char* filename, uint8_t* buffer, int* bufPos, int maxBufPos , uint32_t invokeId, ByteBuffer* response)
|
||||||
|
{
|
||||||
|
uint8_t tag = buffer[(*bufPos)++];
|
||||||
|
int length;
|
||||||
|
|
||||||
|
if (tag != 0x19) {
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*bufPos = BerDecoder_decodeLength(buffer, &length, *bufPos, maxBufPos);
|
||||||
|
|
||||||
|
if (*bufPos < 0) {
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length > 255) {
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(filename, buffer + *bufPos, length);
|
||||||
|
filename[length] = 0;
|
||||||
|
*bufPos += length;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsClient_handleFileOpenRequest(
|
||||||
|
MmsConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId, ByteBuffer* response)
|
||||||
|
{
|
||||||
|
char filename[256];
|
||||||
|
bool hasFileName = false;
|
||||||
|
uint32_t filePosition = 0;
|
||||||
|
|
||||||
|
while (bufPos < maxBufPos) {
|
||||||
|
uint8_t tag = buffer[bufPos++];
|
||||||
|
int length;
|
||||||
|
|
||||||
|
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
|
||||||
|
|
||||||
|
if (bufPos < 0) goto exit_reject_invalid_pdu;
|
||||||
|
|
||||||
|
switch(tag) {
|
||||||
|
case 0xa0: /* filename */
|
||||||
|
|
||||||
|
if (!parseFileName(filename, buffer, &bufPos, bufPos + length, invokeId, response))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hasFileName = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x81: /* initial position */
|
||||||
|
filePosition = BerDecoder_decodeUint32(buffer, length, bufPos);
|
||||||
|
bufPos += length;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* unrecognized parameter */
|
||||||
|
bufPos += length;
|
||||||
|
goto exit_reject_invalid_pdu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasFileName) {
|
||||||
|
|
||||||
|
MmsFileReadStateMachine* frsm = getFreeFrsm(connection);
|
||||||
|
|
||||||
|
if (frsm != NULL) {
|
||||||
|
FileHandle fileHandle = openFile(filename, false);
|
||||||
|
|
||||||
|
if (fileHandle != NULL) {
|
||||||
|
frsm->fileHandle = fileHandle;
|
||||||
|
frsm->readPosition = filePosition;
|
||||||
|
frsm->frsmId = getNextFrsmId(connection);
|
||||||
|
|
||||||
|
mmsServer_createFileOpenResponse(invokeId, response, filename, frsm);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_RESOURCE_OTHER);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto exit_invalid_parameter;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
exit_invalid_parameter:
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
|
||||||
|
return;
|
||||||
|
|
||||||
|
exit_reject_invalid_pdu:
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsClient_handleFileReadRequest(
|
||||||
|
MmsConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId,
|
||||||
|
ByteBuffer* response)
|
||||||
|
{
|
||||||
|
int32_t frsmId = (int32_t) BerDecoder_decodeUint32(buffer, maxBufPos - bufPos, bufPos);
|
||||||
|
|
||||||
|
if (DEBUG_MMS_CLIENT)
|
||||||
|
printf("MMS_CLIENT: mmsClient_handleFileReadRequest read request for frsmId: %i\n", frsmId);
|
||||||
|
|
||||||
|
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
|
||||||
|
|
||||||
|
if (frsm != NULL)
|
||||||
|
mmsMsg_createFileReadResponse(connection, invokeId, response, frsm);
|
||||||
|
else
|
||||||
|
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsClient_handleFileCloseRequest(
|
||||||
|
MmsConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId,
|
||||||
|
ByteBuffer* response)
|
||||||
|
{
|
||||||
|
int32_t frsmId = (int32_t) BerDecoder_decodeUint32(buffer, maxBufPos - bufPos, bufPos);
|
||||||
|
|
||||||
|
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
|
||||||
|
|
||||||
|
FileSystem_closeFile(frsm->fileHandle);
|
||||||
|
frsm->fileHandle = NULL;
|
||||||
|
frsm->frsmId = 0;
|
||||||
|
|
||||||
|
mmsMsg_createFileCloseResponse(invokeId, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
|
|
||||||
void
|
void
|
||||||
mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const char* fileName, uint32_t initialPosition)
|
mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const char* fileName, uint32_t initialPosition)
|
||||||
{
|
{
|
||||||
|
@ -446,26 +662,23 @@ mmsClient_parseFileDirectoryResponse(MmsConnection self, MmsFileDirectoryHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* fileSize, uint64_t* lastModified)
|
mmsMsg_parseFileOpenResponse(uint8_t* buffer, int bufPos, int maxBufPos, int32_t* frsmId, uint32_t* fileSize, uint64_t* lastModified)
|
||||||
{
|
{
|
||||||
uint8_t* buffer = self->lastResponse->buffer;
|
|
||||||
int maxBufPos = self->lastResponse->size;
|
|
||||||
int bufPos = self->lastResponseBufPos;
|
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
uint8_t tag = buffer[bufPos++];
|
uint8_t tag = buffer[bufPos++];
|
||||||
|
|
||||||
if (tag != 0xbf) {
|
if (tag != 0xbf) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
//if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
printf("MMS: mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tag = buffer[bufPos++];
|
tag = buffer[bufPos++];
|
||||||
|
|
||||||
if (tag != 0x48) {
|
if (tag != 0x48) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
//if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
printf("MMS_CLIENT: mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -477,7 +690,7 @@ mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* f
|
||||||
|
|
||||||
if (endPos > maxBufPos) {
|
if (endPos > maxBufPos) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileOpenResponse: message to short (length:%i maxBufPos:%i)!\n", length, maxBufPos);
|
printf("MMS_CLIENT/SERVER: mmsClient_parseFileOpenResponse: message to short (length:%i maxBufPos:%i)!\n", length, maxBufPos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +712,7 @@ mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* f
|
||||||
default:
|
default:
|
||||||
bufPos += length;
|
bufPos += length;
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileOpenResponse: message contains unknown tag %02x!\n", tag);
|
printf("MMS_CLIENT/SERVER: mmsClient_parseFileOpenResponse: message contains unknown tag %02x!\n", tag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,18 +722,15 @@ mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* f
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreFollows, MmsFileReadHandler handler, void* handlerParameter)
|
mmsMsg_parseFileReadResponse(uint8_t* buffer, int bufPos, int maxBufPos, int frsmId, bool* moreFollows, MmsFileReadHandler handler, void* handlerParameter)
|
||||||
{
|
{
|
||||||
uint8_t* buffer = self->lastResponse->buffer;
|
|
||||||
int maxBufPos = self->lastResponse->size;
|
|
||||||
int bufPos = self->lastResponseBufPos;
|
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
uint8_t tag = buffer[bufPos++];
|
uint8_t tag = buffer[bufPos++];
|
||||||
|
|
||||||
if (tag != 0xbf) {
|
if (tag != 0xbf) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileReadResponse: unknown tag %02x\n", tag);
|
printf("MMS_CLIENT/SERVER: mmsClient_parseFileReadResponse: unknown tag %02x\n", tag);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -530,7 +740,7 @@ mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreF
|
||||||
|
|
||||||
if (tag != 0x49) {
|
if (tag != 0x49) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileReadResponse: unknown tag %02x\n", tag);
|
printf("MMS_CLIENT/SERVER: mmsClient_parseFileReadResponse: unknown tag %02x\n", tag);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,7 +752,7 @@ mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreF
|
||||||
|
|
||||||
if (endPos > maxBufPos) {
|
if (endPos > maxBufPos) {
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileReadResponse: message to short (length:%i maxBufPos:%i)!\n", length, maxBufPos);
|
printf("MMS_CLIENT/SERVER: mmsClient_parseFileReadResponse: message to short (length:%i maxBufPos:%i)!\n", length, maxBufPos);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,7 +773,7 @@ mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreF
|
||||||
default:
|
default:
|
||||||
bufPos += length;
|
bufPos += length;
|
||||||
if (DEBUG_MMS_CLIENT)
|
if (DEBUG_MMS_CLIENT)
|
||||||
printf("mmsClient_parseFileReadResponse: message contains unknown tag %02x!\n", tag);
|
printf("MMS_CLIENT/SERVER: mmsClient_parseFileReadResponse: message contains unknown tag %02x!\n", tag);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,6 @@ encodeFileAttributes(uint8_t tag, uint32_t fileSize, char* gtString, uint8_t* bu
|
||||||
+ 2 + gtStringSize;
|
+ 2 + gtStringSize;
|
||||||
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
|
|
||||||
|
|
||||||
return fileAttributesSize;
|
return fileAttributesSize;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -180,8 +178,8 @@ deleteFile(char* fileName) {
|
||||||
return FileSystem_deleteFile(extendedFileName);
|
return FileSystem_deleteFile(extendedFileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm)
|
mmsServer_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm)
|
||||||
{
|
{
|
||||||
uint64_t msTime;
|
uint64_t msTime;
|
||||||
|
|
||||||
|
@ -347,7 +345,7 @@ mmsServer_handleFileOpenRequest(
|
||||||
frsm->readPosition = filePosition;
|
frsm->readPosition = filePosition;
|
||||||
frsm->frsmId = getNextFrsmId(connection);
|
frsm->frsmId = getNextFrsmId(connection);
|
||||||
|
|
||||||
createFileOpenResponse(invokeId, response, filename, frsm);
|
mmsServer_createFileOpenResponse(invokeId, response, filename, frsm);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
|
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_FILE_NON_EXISTENT);
|
||||||
|
@ -370,9 +368,240 @@ exit_reject_invalid_pdu:
|
||||||
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
createFileReadResponse(MmsServerConnection connection, uint32_t invokeId,
|
createObtainFileResponse(uint32_t invokeId, ByteBuffer* response)
|
||||||
|
{
|
||||||
|
createNullResponseExtendedTag(invokeId, response, 0x2e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//#define MMS_FILE_UPLOAD_STATE_COMPLETE 11
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsServer_fileUploadTask(MmsServer self, MmsObtainFileTask task)
|
||||||
|
{
|
||||||
|
//send response message
|
||||||
|
|
||||||
|
/*
|
||||||
|
* states:
|
||||||
|
* 0 - no state / not used
|
||||||
|
* 1 -
|
||||||
|
* 2 - file open sent
|
||||||
|
* 3 - file read sent
|
||||||
|
* 4 - file close sent
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
printf("mmsServer_fileUploadTask (%p) state=%i\n", task, task->state);
|
||||||
|
|
||||||
|
switch (task->state) {
|
||||||
|
case MMS_FILE_UPLOAD_STATE_NOT_USED: /* state: not-used */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMS_FILE_UPLOAD_STATE_FILE_OPEN_SENT:
|
||||||
|
{
|
||||||
|
if (Hal_getTimeInMs() > task->nextTimeout) {
|
||||||
|
printf("MMS_SERVER: file open timeout!\n");
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_RESPONSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMS_FILE_UPLOAD_STATE_SEND_FILE_READ:
|
||||||
|
{
|
||||||
|
ByteBuffer* request = MmsServer_reserveTransmitBuffer(self);
|
||||||
|
|
||||||
|
task->lastRequestInvokeId = MmsServerConnection_getNextRequestInvokeId(task->connection);
|
||||||
|
|
||||||
|
mmsClient_createFileReadRequest(task->lastRequestInvokeId, request, task->frmsId);
|
||||||
|
|
||||||
|
IsoConnection_sendMessage(task->connection->isoConnection, request, false);
|
||||||
|
|
||||||
|
MmsServer_releaseTransmitBuffer(self);
|
||||||
|
|
||||||
|
task->nextTimeout = Hal_getTimeInMs() + 2000; /* timeout 2000 ms */
|
||||||
|
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_FILE_READ_SENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMS_FILE_UPLOAD_STATE_FILE_READ_SENT:
|
||||||
|
|
||||||
|
if (Hal_getTimeInMs() > task->nextTimeout) {
|
||||||
|
printf("MMS_SERVER: file read timeout!\n");
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_RESPONSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMS_FILE_UPLOAD_STATE_SEND_FILE_CLOSE:
|
||||||
|
{
|
||||||
|
ByteBuffer* request = MmsServer_reserveTransmitBuffer(self);
|
||||||
|
|
||||||
|
task->lastRequestInvokeId = MmsServerConnection_getNextRequestInvokeId(task->connection);
|
||||||
|
|
||||||
|
mmsClient_createFileCloseRequest(task->lastRequestInvokeId, request, task->frmsId);
|
||||||
|
|
||||||
|
IsoConnection_sendMessage(task->connection->isoConnection, request, false);
|
||||||
|
|
||||||
|
MmsServer_releaseTransmitBuffer(self);
|
||||||
|
|
||||||
|
task->nextTimeout = Hal_getTimeInMs() + 2000; /* timeout 2000 ms */
|
||||||
|
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_FILE_CLOSE_SENT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMS_FILE_UPLOAD_STATE_FILE_CLOSE_SENT:
|
||||||
|
|
||||||
|
if (Hal_getTimeInMs() > task->nextTimeout) {
|
||||||
|
printf("MMS_SERVER: file close timeout!\n");
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_RESPONSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE:
|
||||||
|
|
||||||
|
// TODO send ObtainFileError
|
||||||
|
|
||||||
|
printf("MMS_SERVER: ObtainFile service: failed to open file from client\n");
|
||||||
|
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_NOT_USED;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
case MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_RESPONSE:
|
||||||
|
{
|
||||||
|
ByteBuffer* response = MmsServer_reserveTransmitBuffer(self);
|
||||||
|
|
||||||
|
createObtainFileResponse(task->obtainFileRequestInvokeId, response);
|
||||||
|
|
||||||
|
IsoConnection_sendMessage(task->connection->isoConnection, response, false);
|
||||||
|
|
||||||
|
MmsServer_releaseTransmitBuffer(self);
|
||||||
|
|
||||||
|
if (self->getFileCompleteHandler)
|
||||||
|
self->getFileCompleteHandler(self->getFileCompleteHandlerParameter, task->connection, task->destinationFilename);
|
||||||
|
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_NOT_USED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsServer_handleObtainFileRequest(
|
||||||
|
MmsServerConnection connection,
|
||||||
|
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||||
|
uint32_t invokeId,
|
||||||
|
ByteBuffer* response)
|
||||||
|
{
|
||||||
|
char sourceFilename[256];
|
||||||
|
bool hasSourceFileName = false;
|
||||||
|
|
||||||
|
char destinationFilename[256];
|
||||||
|
bool hasDestinationFilename = false;
|
||||||
|
|
||||||
|
while (bufPos < maxBufPos) {
|
||||||
|
uint8_t tag = buffer[bufPos++];
|
||||||
|
int length;
|
||||||
|
|
||||||
|
bufPos = BerDecoder_decodeLength(buffer, &length, bufPos, maxBufPos);
|
||||||
|
|
||||||
|
if (bufPos < 0) goto exit_reject_invalid_pdu;
|
||||||
|
|
||||||
|
switch(tag) {
|
||||||
|
|
||||||
|
case 0xa1: /* source filename */
|
||||||
|
|
||||||
|
if (!parseFileName(sourceFilename, buffer, &bufPos, bufPos + length, invokeId, response))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hasSourceFileName = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xa2: /* destination filename */
|
||||||
|
|
||||||
|
if (!parseFileName(destinationFilename, buffer, &bufPos, bufPos + length, invokeId, response))
|
||||||
|
return;
|
||||||
|
|
||||||
|
hasDestinationFilename = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* unrecognized parameter */
|
||||||
|
bufPos += length;
|
||||||
|
goto exit_reject_invalid_pdu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSourceFileName && hasDestinationFilename) {
|
||||||
|
|
||||||
|
/* call callback to check if access is allowed */
|
||||||
|
if (connection->server->obtainFileHandler)
|
||||||
|
if (connection->server->obtainFileHandler(connection->server->obtainFileHandlerParameter, connection, sourceFilename, destinationFilename) == false)
|
||||||
|
goto exit_access_denied;
|
||||||
|
|
||||||
|
//TODO check if destination file already exists. If exists return error message
|
||||||
|
|
||||||
|
printf("Download file %s from client to local file %s...\n", sourceFilename, destinationFilename);
|
||||||
|
|
||||||
|
MmsObtainFileTask task = MmsServer_getObtainFileTask(connection->server);
|
||||||
|
|
||||||
|
if (task != NULL) {
|
||||||
|
|
||||||
|
/* send file open request */
|
||||||
|
task->lastRequestInvokeId = MmsServerConnection_getNextRequestInvokeId(connection);
|
||||||
|
task->connection = connection;
|
||||||
|
|
||||||
|
strcpy(task->destinationFilename, destinationFilename);
|
||||||
|
|
||||||
|
ByteBuffer* request = MmsServer_reserveTransmitBuffer(connection->server);
|
||||||
|
|
||||||
|
mmsClient_createFileOpenRequest(task->lastRequestInvokeId, request, sourceFilename, 0);
|
||||||
|
|
||||||
|
IsoConnection_sendMessage(task->connection->isoConnection, request, false);
|
||||||
|
|
||||||
|
MmsServer_releaseTransmitBuffer(connection->server);
|
||||||
|
|
||||||
|
task->nextTimeout = Hal_getTimeInMs() + 2000; /* timeout 2000 ms */
|
||||||
|
|
||||||
|
task->state = MMS_FILE_UPLOAD_STATE_FILE_OPEN_SENT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto exit_unavailable;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto exit_invalid_parameter;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
exit_invalid_parameter:
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_REQUEST_INVALID_ARGUMENT, response);
|
||||||
|
return;
|
||||||
|
|
||||||
|
exit_access_denied:
|
||||||
|
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_OBJECT_ACCESS_DENIED);
|
||||||
|
return;
|
||||||
|
|
||||||
|
exit_unavailable:
|
||||||
|
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_ACCESS_TEMPORARILY_UNAVAILABLE);
|
||||||
|
return;
|
||||||
|
|
||||||
|
exit_reject_invalid_pdu:
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_INVALID_PDU, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
|
|
||||||
|
void
|
||||||
|
mmsMsg_createFileReadResponse(int maxPduSize, uint32_t invokeId,
|
||||||
ByteBuffer* response, MmsFileReadStateMachine* frsm)
|
ByteBuffer* response, MmsFileReadStateMachine* frsm)
|
||||||
{
|
{
|
||||||
/* determine remaining bytes in file */
|
/* determine remaining bytes in file */
|
||||||
|
@ -380,7 +609,7 @@ createFileReadResponse(MmsServerConnection connection, uint32_t invokeId,
|
||||||
|
|
||||||
uint32_t fileChunkSize = 0;
|
uint32_t fileChunkSize = 0;
|
||||||
|
|
||||||
uint32_t maxFileChunkSize = connection->maxPduSize - 20;
|
uint32_t maxFileChunkSize = maxPduSize - 20;
|
||||||
|
|
||||||
uint32_t fileReadResponseSize = 1; /* for tag */
|
uint32_t fileReadResponseSize = 1; /* for tag */
|
||||||
|
|
||||||
|
@ -442,18 +671,17 @@ mmsServer_handleFileReadRequest(
|
||||||
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
|
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
|
||||||
|
|
||||||
if (frsm != NULL)
|
if (frsm != NULL)
|
||||||
createFileReadResponse(connection, invokeId, response, frsm);
|
mmsMsg_createFileReadResponse(connection->maxPduSize, invokeId, response, frsm);
|
||||||
else
|
else
|
||||||
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER);
|
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
createFileCloseResponse(uint32_t invokeId, ByteBuffer* response)
|
mmsMsg_createFileCloseResponse(uint32_t invokeId, ByteBuffer* response)
|
||||||
{
|
{
|
||||||
createNullResponseExtendedTag(invokeId, response, 0x4a);
|
createNullResponseExtendedTag(invokeId, response, 0x4a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
mmsServer_handleFileCloseRequest(
|
mmsServer_handleFileCloseRequest(
|
||||||
MmsServerConnection connection,
|
MmsServerConnection connection,
|
||||||
|
@ -469,7 +697,7 @@ mmsServer_handleFileCloseRequest(
|
||||||
frsm->fileHandle = NULL;
|
frsm->fileHandle = NULL;
|
||||||
frsm->frsmId = 0;
|
frsm->frsmId = 0;
|
||||||
|
|
||||||
createFileCloseResponse(invokeId, response);
|
mmsMsg_createFileCloseResponse(invokeId, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(MmsServerConn
|
||||||
|
|
||||||
if (DEBUG_MMS_SERVER) printf("MMS_SERVER: sendInfReportSingle variable: %s\n", itemId);
|
if (DEBUG_MMS_SERVER) printf("MMS_SERVER: sendInfReportSingle variable: %s\n", itemId);
|
||||||
|
|
||||||
ByteBuffer* reportBuffer = self->server->reportBuffer;
|
ByteBuffer* reportBuffer = MmsServer_reserveTransmitBuffer(self->server);
|
||||||
|
|
||||||
uint8_t* buffer = reportBuffer->buffer;
|
uint8_t* buffer = reportBuffer->buffer;
|
||||||
int bufPos = 0;
|
int bufPos = 0;
|
||||||
|
@ -82,6 +82,8 @@ MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(MmsServerConn
|
||||||
|
|
||||||
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
|
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
|
||||||
|
|
||||||
|
MmsServer_releaseTransmitBuffer(self->server);
|
||||||
|
|
||||||
exit_function:
|
exit_function:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +153,7 @@ MmsServerConnection_sendInformationReportListOfVariables(
|
||||||
}
|
}
|
||||||
|
|
||||||
/* encode message */
|
/* encode message */
|
||||||
ByteBuffer* reportBuffer = self->server->reportBuffer;
|
ByteBuffer* reportBuffer = MmsServer_reserveTransmitBuffer(self->server);
|
||||||
|
|
||||||
uint8_t* buffer = reportBuffer->buffer;
|
uint8_t* buffer = reportBuffer->buffer;
|
||||||
int bufPos = 0;
|
int bufPos = 0;
|
||||||
|
@ -212,6 +214,8 @@ MmsServerConnection_sendInformationReportListOfVariables(
|
||||||
|
|
||||||
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
|
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
|
||||||
|
|
||||||
|
MmsServer_releaseTransmitBuffer(self->server);
|
||||||
|
|
||||||
exit_function:
|
exit_function:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +268,7 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
|
||||||
|
|
||||||
if (DEBUG_MMS_SERVER) printf("MMS_SERVER: sendInfReport\n");
|
if (DEBUG_MMS_SERVER) printf("MMS_SERVER: sendInfReport\n");
|
||||||
|
|
||||||
ByteBuffer* reportBuffer = self->server->reportBuffer;
|
ByteBuffer* reportBuffer = MmsServer_reserveTransmitBuffer(self->server);
|
||||||
|
|
||||||
uint8_t* buffer = reportBuffer->buffer;
|
uint8_t* buffer = reportBuffer->buffer;
|
||||||
int bufPos = 0;
|
int bufPos = 0;
|
||||||
|
@ -294,6 +298,8 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
|
||||||
|
|
||||||
IsoConnection_sendMessage(self->isoConnection, reportBuffer, false);
|
IsoConnection_sendMessage(self->isoConnection, reportBuffer, false);
|
||||||
|
|
||||||
|
MmsServer_releaseTransmitBuffer(self->server);
|
||||||
|
|
||||||
exit_function:
|
exit_function:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* mms_server.c
|
* mms_server.c
|
||||||
*
|
*
|
||||||
* Copyright 2013, 2014, 2015 Michael Zillgith
|
* Copyright 2013 - 2016 Michael Zillgith
|
||||||
*
|
*
|
||||||
* This file is part of libIEC61850.
|
* This file is part of libIEC61850.
|
||||||
*
|
*
|
||||||
|
@ -60,10 +60,11 @@ MmsServer_create(IsoServer isoServer, MmsDevice* device)
|
||||||
self->valueCaches = createValueCaches(device);
|
self->valueCaches = createValueCaches(device);
|
||||||
self->isLocked = false;
|
self->isLocked = false;
|
||||||
|
|
||||||
self->reportBuffer = ByteBuffer_create(NULL, CONFIG_MMS_MAXIMUM_PDU_SIZE);
|
self->transmitBuffer = ByteBuffer_create(NULL, CONFIG_MMS_MAXIMUM_PDU_SIZE);
|
||||||
|
|
||||||
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
||||||
self->modelMutex = Semaphore_create(1);
|
self->modelMutex = Semaphore_create(1);
|
||||||
|
self->transmitBufferMutex = Semaphore_create(1);
|
||||||
|
|
||||||
IsoServer_setUserLock(isoServer, self->modelMutex);
|
IsoServer_setUserLock(isoServer, self->modelMutex);
|
||||||
#endif
|
#endif
|
||||||
|
@ -87,6 +88,45 @@ MmsServer_unlockModel(MmsServer self)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ByteBuffer*
|
||||||
|
MmsServer_reserveTransmitBuffer(MmsServer self)
|
||||||
|
{
|
||||||
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
||||||
|
Semaphore_wait(self->transmitBufferMutex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return self->transmitBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MmsServer_releaseTransmitBuffer(MmsServer self)
|
||||||
|
{
|
||||||
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
||||||
|
Semaphore_post(self->transmitBufferMutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
|
||||||
|
MmsObtainFileTask
|
||||||
|
MmsServer_getObtainFileTask(MmsServer self)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS; i++) {
|
||||||
|
|
||||||
|
if (self->fileUploadTasks[i].state == 0) {
|
||||||
|
self->fileUploadTasks[i].state = 1;
|
||||||
|
return &(self->fileUploadTasks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
|
|
||||||
void
|
void
|
||||||
MmsServer_installReadHandler(MmsServer self, MmsReadVariableHandler readHandler, void* parameter)
|
MmsServer_installReadHandler(MmsServer self, MmsReadVariableHandler readHandler, void* parameter)
|
||||||
{
|
{
|
||||||
|
@ -151,9 +191,10 @@ MmsServer_destroy(MmsServer self)
|
||||||
|
|
||||||
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
||||||
Semaphore_destroy(self->modelMutex);
|
Semaphore_destroy(self->modelMutex);
|
||||||
|
Semaphore_destroy(self->transmitBufferMutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ByteBuffer_destroy(self->reportBuffer);
|
ByteBuffer_destroy(self->transmitBuffer);
|
||||||
|
|
||||||
GLOBAL_FREEMEM(self);
|
GLOBAL_FREEMEM(self);
|
||||||
}
|
}
|
||||||
|
@ -311,6 +352,22 @@ MmsServer_handleIncomingMessages(MmsServer self)
|
||||||
IsoServer_processIncomingMessages(self->isoServer);
|
IsoServer_processIncomingMessages(self->isoServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MmsServer_handleBackgroundTasks(MmsServer self)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS; i++)
|
||||||
|
{
|
||||||
|
if (self->fileUploadTasks[i].state != 0)
|
||||||
|
mmsServer_fileUploadTask(self, &(self->fileUploadTasks[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MmsServer_stopListeningThreadless(MmsServer self)
|
MmsServer_stopListeningThreadless(MmsServer self)
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,6 +111,12 @@ handleConfirmedRequestPdu(
|
||||||
if (extendedTag) {
|
if (extendedTag) {
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
case 0x2e: /* obtain-file */
|
||||||
|
mmsServer_handleObtainFileRequest(self, buffer, bufPos, bufPos + length, invokeId, response);
|
||||||
|
break;
|
||||||
|
#endif /* MMS_OBTAIN_FILE_SERVICE == 1 */
|
||||||
|
|
||||||
#if (MMS_JOURNAL_SERVICE == 1)
|
#if (MMS_JOURNAL_SERVICE == 1)
|
||||||
case 0x41: /* read-journal */
|
case 0x41: /* read-journal */
|
||||||
mmsServer_handleReadJournalRequest(self, buffer, bufPos, bufPos + length, invokeId, response);
|
mmsServer_handleReadJournalRequest(self, buffer, bufPos, bufPos + length, invokeId, response);
|
||||||
|
@ -234,6 +240,199 @@ handleConfirmedRequestPdu(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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)) {
|
||||||
|
|
||||||
|
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].lastRequestInvokeId == invokeId) {
|
||||||
|
|
||||||
|
self->server->fileUploadTasks[i].state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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(void* parameter, int32_t frsmId, uint8_t* buffer, uint32_t bytesReceived)
|
||||||
|
{
|
||||||
|
MmsObtainFileTask task = (MmsObtainFileTask) parameter;
|
||||||
|
|
||||||
|
printf(" FILE %i received %i bytes\n", frsmId, bytesReceived);
|
||||||
|
//TODO write data to file
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extendedTag) {
|
||||||
|
switch(tag) {
|
||||||
|
|
||||||
|
#if (MMS_FILE_SERVICE == 1)
|
||||||
|
case 0x48: /* file-open-response */
|
||||||
|
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)) {
|
||||||
|
printf("MMS_SERVER: received file-open-response with frmsId=%i\n", frmsId);
|
||||||
|
|
||||||
|
fileTask->frmsId = frmsId;
|
||||||
|
fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_FILE_READ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("MMS_SERVER: error parsing file-open-response\n");
|
||||||
|
fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("MMS_SERVER: unexpected file-open-response\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x49: /* file-read-response */
|
||||||
|
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, fileTask->frmsId, &moreFollows, mmsFileReadHandler, (void*) fileTask)) {
|
||||||
|
|
||||||
|
printf("MMS_SERVER: received file data\n");
|
||||||
|
|
||||||
|
if (moreFollows) {
|
||||||
|
fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_FILE_READ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
//TODO close local file
|
||||||
|
|
||||||
|
fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_FILE_CLOSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_ERROR_SOURCE;
|
||||||
|
printf("MMS_SERVER: error parsing file-read-response\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("MMS_SERVER: unexpected file-read-response\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x4a: /* file-close-response */
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("MMS_SERVER: received file-close-response\n");
|
||||||
|
|
||||||
|
|
||||||
|
MmsObtainFileTask fileTask = getUploadTaskByInvokeId(self->server, invokeId);
|
||||||
|
|
||||||
|
if (fileTask != NULL) {
|
||||||
|
fileTask->state = MMS_FILE_UPLOAD_STATE_SEND_OBTAIN_FILE_RESPONSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
printf("MMS_SERVER: unexpected file-close-response\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* MMS_FILE_SERVICE == 1 */
|
||||||
|
|
||||||
|
default:
|
||||||
|
mmsServer_writeMmsRejectPdu(&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:
|
||||||
|
mmsServer_writeMmsRejectPdu(&invokeId, MMS_ERROR_REJECT_UNRECOGNIZED_SERVICE, response);
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bufPos += length;
|
||||||
|
}
|
||||||
|
} /* handleConfirmedResponsePdu */
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
|
|
||||||
MmsIndication
|
MmsIndication
|
||||||
MmsServerConnection_parseMessage(MmsServerConnection self, ByteBuffer* message, ByteBuffer* response)
|
MmsServerConnection_parseMessage(MmsServerConnection self, ByteBuffer* message, ByteBuffer* response)
|
||||||
{
|
{
|
||||||
|
@ -266,6 +465,17 @@ MmsServerConnection_parseMessage(MmsServerConnection self, ByteBuffer* message,
|
||||||
handleConfirmedRequestPdu(self, buffer, bufPos, bufPos + pduLength, response);
|
handleConfirmedRequestPdu(self, buffer, bufPos, bufPos + pduLength, response);
|
||||||
retVal = MMS_CONFIRMED_REQUEST;
|
retVal = MMS_CONFIRMED_REQUEST;
|
||||||
break;
|
break;
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
case 0xa1: /* Confirmed response PDU */
|
||||||
|
handleConfirmedResponsePdu(self, buffer, bufPos, bufPos + pduLength, response);
|
||||||
|
retVal = MMS_CONFIRMED_REQUEST;
|
||||||
|
break;
|
||||||
|
case 0xa2: /* Confirmed error PDU */
|
||||||
|
handleConfirmedErrorPdu(self, buffer, 0, bufPos + pduLength, response);
|
||||||
|
retVal = MMS_CONFIRMED_REQUEST;
|
||||||
|
break;
|
||||||
|
|
||||||
|
#endif /* (MMS_OBTAIN_FILE_SERVICE == 1) */
|
||||||
case 0x8b: /* Conclude request PDU */
|
case 0x8b: /* Conclude request PDU */
|
||||||
mmsServer_writeConcludeResponsePdu(response);
|
mmsServer_writeConcludeResponsePdu(response);
|
||||||
retVal = MMS_CONCLUDE;
|
retVal = MMS_CONCLUDE;
|
||||||
|
@ -317,6 +527,10 @@ MmsServerConnection_init(MmsServerConnection connection, MmsServer server, IsoCo
|
||||||
self->namedVariableLists = LinkedList_create();
|
self->namedVariableLists = LinkedList_create();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||||
|
self->lastRequestInvokeId = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
IsoConnection_installListener(isoCon, messageReceived, (void*) self);
|
IsoConnection_installListener(isoCon, messageReceived, (void*) self);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
@ -391,3 +605,10 @@ MmsServerConnection_getLastInvokeId(MmsServerConnection self)
|
||||||
{
|
{
|
||||||
return self->lastInvokeId;
|
return self->lastInvokeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self)
|
||||||
|
{
|
||||||
|
self->lastRequestInvokeId++;
|
||||||
|
return self->lastRequestInvokeId;
|
||||||
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ int
|
||||||
mmsServer_createMmsWriteResponse(MmsServerConnection connection,
|
mmsServer_createMmsWriteResponse(MmsServerConnection connection,
|
||||||
int invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults)
|
int invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults)
|
||||||
{
|
{
|
||||||
|
//TODO remove asn1c code
|
||||||
MmsPdu_t* mmsPdu = mmsServer_createConfirmedResponse(invokeId);
|
MmsPdu_t* mmsPdu = mmsServer_createConfirmedResponse(invokeId);
|
||||||
|
|
||||||
mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present =
|
mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present =
|
||||||
|
@ -75,13 +76,15 @@ mmsServer_createMmsWriteResponse(MmsServerConnection connection,
|
||||||
void
|
void
|
||||||
MmsServerConnection_sendWriteResponse(MmsServerConnection self, uint32_t invokeId, MmsDataAccessError indication, bool handlerMode)
|
MmsServerConnection_sendWriteResponse(MmsServerConnection self, uint32_t invokeId, MmsDataAccessError indication, bool handlerMode)
|
||||||
{
|
{
|
||||||
ByteBuffer* response = ByteBuffer_create(NULL, self->maxPduSize);
|
ByteBuffer* response = MmsServer_reserveTransmitBuffer(self->server);
|
||||||
|
|
||||||
|
ByteBuffer_setSize(response, 0);
|
||||||
|
|
||||||
mmsServer_createMmsWriteResponse(self, invokeId, response, 1, &indication);
|
mmsServer_createMmsWriteResponse(self, invokeId, response, 1, &indication);
|
||||||
|
|
||||||
IsoConnection_sendMessage(self->isoConnection, response, handlerMode);
|
IsoConnection_sendMessage(self->isoConnection, response, handlerMode);
|
||||||
|
|
||||||
ByteBuffer_destroy(response);
|
MmsServer_releaseTransmitBuffer(self->server);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -54,10 +54,10 @@
|
||||||
struct sIsoConnection
|
struct sIsoConnection
|
||||||
{
|
{
|
||||||
uint8_t* receiveBuffer;
|
uint8_t* receiveBuffer;
|
||||||
uint8_t* sendBuffer;
|
|
||||||
|
|
||||||
ByteBuffer rcvBuffer;
|
ByteBuffer rcvBuffer;
|
||||||
|
|
||||||
|
uint8_t* sendBuffer;
|
||||||
|
|
||||||
uint8_t* cotpReadBuf;
|
uint8_t* cotpReadBuf;
|
||||||
uint8_t* cotpWriteBuf;
|
uint8_t* cotpWriteBuf;
|
||||||
ByteBuffer cotpReadBuffer;
|
ByteBuffer cotpReadBuffer;
|
||||||
|
|
|
@ -551,3 +551,6 @@ EXPORTS
|
||||||
ModelNode_getType
|
ModelNode_getType
|
||||||
ControlObjectClient_setTestMode
|
ControlObjectClient_setTestMode
|
||||||
LogStorage_setMaxLogEntries
|
LogStorage_setMaxLogEntries
|
||||||
|
MmsServer_installObtainFileHandler
|
||||||
|
MmsServer_installGetFileCompleteHandler
|
||||||
|
MmsServer_handleBackgroundTasks
|
||||||
|
|
|
@ -629,3 +629,6 @@ EXPORTS
|
||||||
ModelNode_getType
|
ModelNode_getType
|
||||||
ControlObjectClient_setTestMode
|
ControlObjectClient_setTestMode
|
||||||
LogStorage_setMaxLogEntries
|
LogStorage_setMaxLogEntries
|
||||||
|
MmsServer_installObtainFileHandler
|
||||||
|
MmsServer_installGetFileCompleteHandler
|
||||||
|
MmsServer_handleBackgroundTasks
|
||||||
|
|
Loading…
Add table
Reference in a new issue