- 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) */
|
||||
#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 */
|
||||
#define MMS_DEFAULT_PROFILE 1
|
||||
|
||||
|
@ -194,6 +197,7 @@
|
|||
#define MMS_STATUS_SERVICE 1
|
||||
#define MMS_IDENTIFY_SERVICE 1
|
||||
#define MMS_FILE_SERVICE 1
|
||||
#define MMS_OBTAIN_FILE_SERVICE 1
|
||||
#endif /* MMS_DEFAULT_PROFILE */
|
||||
|
||||
#if (MMS_WRITE_SERVICE != 1)
|
||||
|
@ -216,7 +220,7 @@
|
|||
/* use short FC defines as in old API */
|
||||
#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
|
||||
|
||||
#endif /* STACK_CONFIG_H_ */
|
||||
|
|
|
@ -186,6 +186,7 @@
|
|||
#define MMS_STATUS_SERVICE 1
|
||||
#define MMS_IDENTIFY_SERVICE 1
|
||||
#define MMS_FILE_SERVICE 1
|
||||
#define MMS_OBTAIN_FILE_SERVICE 1
|
||||
#endif /* MMS_DEFAULT_PROFILE */
|
||||
|
||||
#if (MMS_WRITE_SERVICE != 1)
|
||||
|
|
|
@ -35,6 +35,7 @@ DataAttribute* toDataAttribute(ModelNode * MN)
|
|||
%include "iec61850_server.h"
|
||||
%include "iec61850_dynamic_model.h"
|
||||
%include "iec61850_cdc.h"
|
||||
%include "linked_list.h
|
||||
ModelNode* toModelNode(LogicalNode *);
|
||||
ModelNode* toModelNode(DataObject *);
|
||||
DataAttribute* toDataAttribute(DataObject *);
|
||||
|
|
|
@ -3021,6 +3021,9 @@ processPeriodicTasks(MmsMapping* self)
|
|||
#if (CONFIG_IEC61850_LOG_SERVICE == 1)
|
||||
Logging_processIntegrityLogs(self, currentTimeInMs);
|
||||
#endif
|
||||
|
||||
/* handle low priority MMS backgound tasks (like file upload...) */
|
||||
MmsServer_handleBackgroundTasks(self->mmsServer);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -661,9 +661,13 @@ typedef void
|
|||
typedef void
|
||||
(*MmsFileReadHandler) (void* parameter, int32_t frsmId, uint8_t* buffer, uint32_t bytesReceived);
|
||||
|
||||
|
||||
/**
|
||||
* \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
|
||||
*/
|
||||
int32_t
|
||||
|
|
|
@ -124,6 +124,17 @@ typedef MmsError (*MmsNamedVariableListChangedHandler)(void* parameter, bool cre
|
|||
void
|
||||
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
|
||||
*
|
||||
|
@ -209,6 +220,14 @@ MmsServer_waitReady(MmsServer self, unsigned int timeoutMs);
|
|||
void
|
||||
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)
|
||||
*
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include "hal_thread.h"
|
||||
|
||||
#include "mms_common_internal.h"
|
||||
|
||||
#ifndef CONFIG_MMS_RAW_MESSAGE_LOGGING
|
||||
#define CONFIG_MMS_RAW_MESSAGE_LOGGING 0
|
||||
#endif
|
||||
|
@ -96,6 +98,11 @@ struct sMmsConnection {
|
|||
|
||||
/* state of an active connection conclude/release process */
|
||||
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
|
||||
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
|
||||
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
|
||||
mmsClient_createFileCloseRequest(uint32_t invokeId, ByteBuffer* request, int32_t frsmId);
|
||||
|
||||
|
@ -280,4 +281,25 @@ mmsClient_createReadJournalRequestStartAfter(uint32_t invokeId, ByteBuffer* requ
|
|||
bool
|
||||
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_ */
|
||||
|
|
|
@ -27,6 +27,50 @@
|
|||
#include "mms_value.h"
|
||||
#include "MmsPdu.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*
|
||||
mmsMsg_parseDataElement(Data_t* dataElement);
|
||||
|
|
|
@ -98,6 +98,9 @@ MmsServerConnection_sendWriteResponse(MmsServerConnection self, uint32_t invokeI
|
|||
uint32_t
|
||||
MmsServerConnection_getLastInvokeId(MmsServerConnection self);
|
||||
|
||||
uint32_t
|
||||
MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self);
|
||||
|
||||
#endif /* MMS_SERVER_CONNECTION_H_ */
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include "libiec61850_platform_includes.h"
|
||||
|
||||
#include <MmsPdu.h>
|
||||
#include "MmsPdu.h"
|
||||
#include "mms_common.h"
|
||||
#include "mms_indication.h"
|
||||
#include "mms_server_connection.h"
|
||||
|
@ -44,6 +44,11 @@
|
|||
#include "ber_encoder.h"
|
||||
#include "ber_decode.h"
|
||||
|
||||
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||
#include "hal_filesystem.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DEBUG_MMS_SERVER
|
||||
#define DEBUG_MMS_SERVER 0
|
||||
#endif
|
||||
|
@ -60,6 +65,42 @@
|
|||
#define MMS_FILE_SERVICE 1
|
||||
#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 {
|
||||
IsoServer isoServer;
|
||||
MmsDevice* device;
|
||||
|
@ -83,7 +124,10 @@ struct sMmsServer {
|
|||
Map valueCaches;
|
||||
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)
|
||||
Semaphore modelMutex;
|
||||
|
@ -101,24 +145,18 @@ struct sMmsServer {
|
|||
char* modelName;
|
||||
char* revision;
|
||||
#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
|
||||
#define CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION 5
|
||||
MmsGetFileCompleteHandler getFileCompleteHandler;
|
||||
void* getFileCompleteHandlerParameter;
|
||||
|
||||
struct sMmsObtainFileTask fileUploadTasks[CONFIG_MMS_SERVER_MAX_GET_FILE_TASKS];
|
||||
#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 {
|
||||
int maxServOutstandingCalling;
|
||||
|
@ -129,6 +167,10 @@ struct sMmsServerConnection {
|
|||
MmsServer server;
|
||||
uint32_t lastInvokeId;
|
||||
|
||||
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||
uint32_t lastRequestInvokeId; /* only used by obtainFile service */
|
||||
#endif
|
||||
|
||||
#if (MMS_DYNAMIC_DATA_SETS == 1)
|
||||
LinkedList /*<MmsNamedVariableList>*/namedVariableLists; /* aa-specific named variable lists */
|
||||
#endif
|
||||
|
@ -137,13 +179,25 @@ struct sMmsServerConnection {
|
|||
int32_t nextFrsmId;
|
||||
MmsFileReadStateMachine frsms[CONFIG_MMS_MAX_NUMBER_OF_OPEN_FILES_PER_CONNECTION];
|
||||
#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 */
|
||||
int
|
||||
mmsServer_write_out(const void *buffer, size_t size, void *app_key);
|
||||
|
||||
|
||||
|
||||
void
|
||||
mmsServer_handleDeleteNamedVariableListRequest(MmsServerConnection connection,
|
||||
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||
|
@ -275,6 +329,13 @@ mmsServer_handleFileCloseRequest(
|
|||
uint32_t invokeId,
|
||||
ByteBuffer* response);
|
||||
|
||||
void
|
||||
mmsServer_handleObtainFileRequest(
|
||||
MmsServerConnection connection,
|
||||
uint8_t* buffer, int bufPos, int maxBufPos,
|
||||
uint32_t invokeId,
|
||||
ByteBuffer* response);
|
||||
|
||||
int
|
||||
mmsServer_isIndexAccess(AlternateAccess_t* alternateAccess);
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ sendRequestAndWaitForResponse(MmsConnection self, uint32_t invokeId, ByteBuffer*
|
|||
|
||||
if (!success) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -372,12 +372,6 @@ waitUntilLastResponseHasBeenProcessed(MmsConnection self)
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct sMmsServiceError
|
||||
{
|
||||
int errorClass;
|
||||
int errorCode;
|
||||
} MmsServiceError;
|
||||
|
||||
static MmsError
|
||||
convertServiceErrorToMmsError(MmsServiceError serviceError)
|
||||
{
|
||||
|
@ -519,12 +513,9 @@ parseServiceError(uint8_t* buffer, int bufPos, int maxLength, MmsServiceError* e
|
|||
return bufPos;
|
||||
}
|
||||
|
||||
static int
|
||||
parseConfirmedErrorPDU(ByteBuffer* message, uint32_t* invokeId, MmsServiceError* serviceError)
|
||||
int
|
||||
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;
|
||||
|
||||
uint8_t tag = buffer[bufPos++];
|
||||
|
@ -675,7 +666,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
|
|||
uint32_t invokeId;
|
||||
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)
|
||||
printf("MMS_CLIENT: Error parsing confirmedErrorPDU!\n");
|
||||
}
|
||||
|
@ -742,6 +733,124 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
|
|||
else
|
||||
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)
|
||||
printf("MMS_CLIENT: LEAVE mmsIsoCallback - OK\n");
|
||||
|
@ -752,6 +861,7 @@ mmsIsoCallback(IsoIndication indication, void* parameter, ByteBuffer* payload)
|
|||
|
||||
if (DEBUG_MMS_CLIENT)
|
||||
printf("received malformed message from server!\n");
|
||||
|
||||
IsoClientConnection_releaseReceiveBuffer(self->isoClient);
|
||||
|
||||
|
||||
|
@ -1811,7 +1921,12 @@ MmsConnection_fileOpen(MmsConnection self, MmsError* mmsError, const char* filen
|
|||
if (self->lastResponseError != MMS_ERROR_NONE)
|
||||
*mmsError = self->lastResponseError;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1890,7 +2005,11 @@ MmsConnection_fileRead(MmsConnection self, MmsError* mmsError, int32_t frsmId, M
|
|||
if (self->lastResponseError != MMS_ERROR_NONE)
|
||||
*mmsError = self->lastResponseError;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1968,14 +2087,17 @@ MmsConnection_obtainFile(MmsConnection self, MmsError* mmsError, const char* sou
|
|||
|
||||
uint32_t invokeId = getNextInvokeId(self);
|
||||
|
||||
//TODO enable file service
|
||||
|
||||
mmsClient_createObtainFileRequest(invokeId, payload, sourceFile, destinationFile);
|
||||
|
||||
sendRequestAndWaitForResponse(self, invokeId, payload);
|
||||
|
||||
ByteBuffer* responseMessage = sendRequestAndWaitForResponse(self, invokeId, payload);
|
||||
|
||||
if (self->lastResponseError != MMS_ERROR_NONE)
|
||||
*mmsError = self->lastResponseError;
|
||||
|
||||
/* nothing to do - response contains no data to evaluate */
|
||||
|
||||
releaseResponse(self);
|
||||
|
||||
if (self->associationState == MMS_STATE_CLOSED)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* mms_client_files.c
|
||||
*
|
||||
* Copyright 2013, 2014 Michael Zillgith
|
||||
* Copyright 2013 - 2016 Michael Zillgith
|
||||
*
|
||||
* This file is part of libIEC61850.
|
||||
*
|
||||
|
@ -32,6 +32,222 @@
|
|||
#include "ber_decode.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
|
||||
mmsClient_createFileOpenRequest(uint32_t invokeId, ByteBuffer* request, const char* fileName, uint32_t initialPosition)
|
||||
{
|
||||
|
@ -446,26 +662,23 @@ mmsClient_parseFileDirectoryResponse(MmsConnection self, MmsFileDirectoryHandler
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
uint8_t tag = buffer[bufPos++];
|
||||
|
||||
if (tag != 0xbf) {
|
||||
if (DEBUG_MMS_CLIENT)
|
||||
printf("mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
||||
//if (DEBUG_MMS_CLIENT)
|
||||
printf("MMS: mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
tag = buffer[bufPos++];
|
||||
|
||||
if (tag != 0x48) {
|
||||
if (DEBUG_MMS_CLIENT)
|
||||
printf("mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
||||
//if (DEBUG_MMS_CLIENT)
|
||||
printf("MMS_CLIENT: mmsClient_parseFileOpenResponse: unknown tag %02x\n", tag);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -477,7 +690,7 @@ mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* f
|
|||
|
||||
if (endPos > maxBufPos) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -499,7 +712,7 @@ mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* f
|
|||
default:
|
||||
bufPos += length;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -509,18 +722,15 @@ mmsClient_parseFileOpenResponse(MmsConnection self, int32_t* frsmId, uint32_t* f
|
|||
|
||||
|
||||
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;
|
||||
|
||||
uint8_t tag = buffer[bufPos++];
|
||||
|
||||
if (tag != 0xbf) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -530,7 +740,7 @@ mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreF
|
|||
|
||||
if (tag != 0x49) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -542,7 +752,7 @@ mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreF
|
|||
|
||||
if (endPos > maxBufPos) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -563,7 +773,7 @@ mmsClient_parseFileReadResponse(MmsConnection self, int32_t frsmId, bool* moreF
|
|||
default:
|
||||
bufPos += length;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -110,8 +110,6 @@ encodeFileAttributes(uint8_t tag, uint32_t fileSize, char* gtString, uint8_t* bu
|
|||
+ 2 + gtStringSize;
|
||||
|
||||
if (buffer == NULL) {
|
||||
|
||||
|
||||
return fileAttributesSize;
|
||||
}
|
||||
else {
|
||||
|
@ -180,8 +178,8 @@ deleteFile(char* fileName) {
|
|||
return FileSystem_deleteFile(extendedFileName);
|
||||
}
|
||||
|
||||
static void
|
||||
createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm)
|
||||
void
|
||||
mmsServer_createFileOpenResponse(uint32_t invokeId, ByteBuffer* response, char* fullPath, MmsFileReadStateMachine* frsm)
|
||||
{
|
||||
uint64_t msTime;
|
||||
|
||||
|
@ -347,7 +345,7 @@ mmsServer_handleFileOpenRequest(
|
|||
frsm->readPosition = filePosition;
|
||||
frsm->frsmId = getNextFrsmId(connection);
|
||||
|
||||
createFileOpenResponse(invokeId, response, filename, frsm);
|
||||
mmsServer_createFileOpenResponse(invokeId, response, filename, frsm);
|
||||
}
|
||||
else
|
||||
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);
|
||||
}
|
||||
|
||||
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||
|
||||
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)
|
||||
{
|
||||
/* determine remaining bytes in file */
|
||||
|
@ -380,7 +609,7 @@ createFileReadResponse(MmsServerConnection connection, uint32_t invokeId,
|
|||
|
||||
uint32_t fileChunkSize = 0;
|
||||
|
||||
uint32_t maxFileChunkSize = connection->maxPduSize - 20;
|
||||
uint32_t maxFileChunkSize = maxPduSize - 20;
|
||||
|
||||
uint32_t fileReadResponseSize = 1; /* for tag */
|
||||
|
||||
|
@ -442,18 +671,17 @@ mmsServer_handleFileReadRequest(
|
|||
MmsFileReadStateMachine* frsm = getFrsm(connection, frsmId);
|
||||
|
||||
if (frsm != NULL)
|
||||
createFileReadResponse(connection, invokeId, response, frsm);
|
||||
mmsMsg_createFileReadResponse(connection->maxPduSize, invokeId, response, frsm);
|
||||
else
|
||||
mmsServer_createServiceErrorPdu(invokeId, response, MMS_ERROR_FILE_OTHER);
|
||||
}
|
||||
|
||||
static void
|
||||
createFileCloseResponse(uint32_t invokeId, ByteBuffer* response)
|
||||
void
|
||||
mmsMsg_createFileCloseResponse(uint32_t invokeId, ByteBuffer* response)
|
||||
{
|
||||
createNullResponseExtendedTag(invokeId, response, 0x4a);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mmsServer_handleFileCloseRequest(
|
||||
MmsServerConnection connection,
|
||||
|
@ -469,7 +697,7 @@ mmsServer_handleFileCloseRequest(
|
|||
frsm->fileHandle = NULL;
|
||||
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);
|
||||
|
||||
ByteBuffer* reportBuffer = self->server->reportBuffer;
|
||||
ByteBuffer* reportBuffer = MmsServer_reserveTransmitBuffer(self->server);
|
||||
|
||||
uint8_t* buffer = reportBuffer->buffer;
|
||||
int bufPos = 0;
|
||||
|
@ -82,6 +82,8 @@ MmsServerConnection_sendInformationReportSingleVariableVMDSpecific(MmsServerConn
|
|||
|
||||
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
|
||||
|
||||
MmsServer_releaseTransmitBuffer(self->server);
|
||||
|
||||
exit_function:
|
||||
return;
|
||||
}
|
||||
|
@ -151,7 +153,7 @@ MmsServerConnection_sendInformationReportListOfVariables(
|
|||
}
|
||||
|
||||
/* encode message */
|
||||
ByteBuffer* reportBuffer = self->server->reportBuffer;
|
||||
ByteBuffer* reportBuffer = MmsServer_reserveTransmitBuffer(self->server);
|
||||
|
||||
uint8_t* buffer = reportBuffer->buffer;
|
||||
int bufPos = 0;
|
||||
|
@ -212,6 +214,8 @@ MmsServerConnection_sendInformationReportListOfVariables(
|
|||
|
||||
IsoConnection_sendMessage(self->isoConnection, reportBuffer, handlerMode);
|
||||
|
||||
MmsServer_releaseTransmitBuffer(self->server);
|
||||
|
||||
exit_function:
|
||||
return;
|
||||
}
|
||||
|
@ -264,7 +268,7 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
|
|||
|
||||
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;
|
||||
int bufPos = 0;
|
||||
|
@ -294,6 +298,8 @@ MmsServerConnection_sendInformationReportVMDSpecific(MmsServerConnection self, c
|
|||
|
||||
IsoConnection_sendMessage(self->isoConnection, reportBuffer, false);
|
||||
|
||||
MmsServer_releaseTransmitBuffer(self->server);
|
||||
|
||||
exit_function:
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* mms_server.c
|
||||
*
|
||||
* Copyright 2013, 2014, 2015 Michael Zillgith
|
||||
* Copyright 2013 - 2016 Michael Zillgith
|
||||
*
|
||||
* This file is part of libIEC61850.
|
||||
*
|
||||
|
@ -60,10 +60,11 @@ MmsServer_create(IsoServer isoServer, MmsDevice* device)
|
|||
self->valueCaches = createValueCaches(device);
|
||||
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)
|
||||
self->modelMutex = Semaphore_create(1);
|
||||
self->transmitBufferMutex = Semaphore_create(1);
|
||||
|
||||
IsoServer_setUserLock(isoServer, self->modelMutex);
|
||||
#endif
|
||||
|
@ -87,6 +88,45 @@ MmsServer_unlockModel(MmsServer self)
|
|||
#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
|
||||
MmsServer_installReadHandler(MmsServer self, MmsReadVariableHandler readHandler, void* parameter)
|
||||
{
|
||||
|
@ -151,9 +191,10 @@ MmsServer_destroy(MmsServer self)
|
|||
|
||||
#if (CONFIG_MMS_THREADLESS_STACK != 1)
|
||||
Semaphore_destroy(self->modelMutex);
|
||||
Semaphore_destroy(self->transmitBufferMutex);
|
||||
#endif
|
||||
|
||||
ByteBuffer_destroy(self->reportBuffer);
|
||||
ByteBuffer_destroy(self->transmitBuffer);
|
||||
|
||||
GLOBAL_FREEMEM(self);
|
||||
}
|
||||
|
@ -311,6 +352,22 @@ MmsServer_handleIncomingMessages(MmsServer self)
|
|||
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
|
||||
MmsServer_stopListeningThreadless(MmsServer self)
|
||||
{
|
||||
|
|
|
@ -111,6 +111,12 @@ handleConfirmedRequestPdu(
|
|||
if (extendedTag) {
|
||||
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)
|
||||
case 0x41: /* read-journal */
|
||||
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
|
||||
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);
|
||||
retVal = MMS_CONFIRMED_REQUEST;
|
||||
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 */
|
||||
mmsServer_writeConcludeResponsePdu(response);
|
||||
retVal = MMS_CONCLUDE;
|
||||
|
@ -317,6 +527,10 @@ MmsServerConnection_init(MmsServerConnection connection, MmsServer server, IsoCo
|
|||
self->namedVariableLists = LinkedList_create();
|
||||
#endif
|
||||
|
||||
#if (MMS_OBTAIN_FILE_SERVICE == 1)
|
||||
self->lastRequestInvokeId = 0;
|
||||
#endif
|
||||
|
||||
IsoConnection_installListener(isoCon, messageReceived, (void*) self);
|
||||
|
||||
return self;
|
||||
|
@ -391,3 +605,10 @@ MmsServerConnection_getLastInvokeId(MmsServerConnection self)
|
|||
{
|
||||
return self->lastInvokeId;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
MmsServerConnection_getNextRequestInvokeId(MmsServerConnection self)
|
||||
{
|
||||
self->lastRequestInvokeId++;
|
||||
return self->lastRequestInvokeId;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ int
|
|||
mmsServer_createMmsWriteResponse(MmsServerConnection connection,
|
||||
int invokeId, ByteBuffer* response, int numberOfItems, MmsDataAccessError* accessResults)
|
||||
{
|
||||
//TODO remove asn1c code
|
||||
MmsPdu_t* mmsPdu = mmsServer_createConfirmedResponse(invokeId);
|
||||
|
||||
mmsPdu->choice.confirmedResponsePdu.confirmedServiceResponse.present =
|
||||
|
@ -75,13 +76,15 @@ mmsServer_createMmsWriteResponse(MmsServerConnection connection,
|
|||
void
|
||||
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);
|
||||
|
||||
IsoConnection_sendMessage(self->isoConnection, response, handlerMode);
|
||||
|
||||
ByteBuffer_destroy(response);
|
||||
MmsServer_releaseTransmitBuffer(self->server);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -54,10 +54,10 @@
|
|||
struct sIsoConnection
|
||||
{
|
||||
uint8_t* receiveBuffer;
|
||||
uint8_t* sendBuffer;
|
||||
|
||||
ByteBuffer rcvBuffer;
|
||||
|
||||
uint8_t* sendBuffer;
|
||||
|
||||
uint8_t* cotpReadBuf;
|
||||
uint8_t* cotpWriteBuf;
|
||||
ByteBuffer cotpReadBuffer;
|
||||
|
|
|
@ -551,3 +551,6 @@ EXPORTS
|
|||
ModelNode_getType
|
||||
ControlObjectClient_setTestMode
|
||||
LogStorage_setMaxLogEntries
|
||||
MmsServer_installObtainFileHandler
|
||||
MmsServer_installGetFileCompleteHandler
|
||||
MmsServer_handleBackgroundTasks
|
||||
|
|
|
@ -629,3 +629,6 @@ EXPORTS
|
|||
ModelNode_getType
|
||||
ControlObjectClient_setTestMode
|
||||
LogStorage_setMaxLogEntries
|
||||
MmsServer_installObtainFileHandler
|
||||
MmsServer_installGetFileCompleteHandler
|
||||
MmsServer_handleBackgroundTasks
|
||||
|
|
Loading…
Add table
Reference in a new issue