#include #include #include #include #include "testing_networklayers.h" typedef struct NetworkLayer_FileInput { UA_Connection connection; UA_UInt32 files; char **filenames; UA_UInt32 files_read; UA_StatusCode (*writeCallback)(struct NetworkLayer_FileInput *handle, const UA_ByteString *buf); void (*readCallback)(void); void *callbackHandle; } NetworkLayer_FileInput; /** Accesses only the sockfd in the handle. Can be run from parallel threads. */ static UA_StatusCode writeCallback(NetworkLayer_FileInput *handle, const UA_ByteString *buf) { handle->writeCallback(handle->callbackHandle, buf); return UA_STATUSCODE_GOOD; } static void closeCallback(NetworkLayer_FileInput *handle) { } static UA_StatusCode NetworkLayer_FileInput_start(NetworkLayer_FileInput *layer, UA_Logger *logger) { return UA_STATUSCODE_GOOD; } static UA_Int32 NetworkLayer_FileInput_getWork(NetworkLayer_FileInput *layer, UA_WorkItem **workItems, UA_UInt16 timeout) { layer->readCallback(); // open a new connection // return a single buffer with the entire file if(layer->files >= layer->files_read) return 0; int filefd = open(layer->filenames[layer->files_read], O_RDONLY); layer->files_read++; if(filefd == -1) return 0; UA_Byte *buf = malloc(layer->connection.localConf.maxMessageSize); UA_Int32 bytes_read = read(filefd, buf, layer->connection.localConf.maxMessageSize); close(filefd); if(bytes_read <= 0) { free(buf); return 0; } *workItems = malloc(sizeof(UA_WorkItem)); UA_WorkItem *work = *workItems; work->type = UA_WORKITEMTYPE_BINARYMESSAGE; work->work.binaryMessage.connection = &layer->connection; work->work.binaryMessage.message = (UA_ByteString){.length = bytes_read, .data = (UA_Byte*)buf}; return 1; } static UA_Int32 NetworkLayer_FileInput_stop(NetworkLayer_FileInput * layer, UA_WorkItem **workItems) { // remove the connection in the server // return removeAllConnections(layer, workItems); return 0; } static void NetworkLayer_FileInput_delete(NetworkLayer_FileInput *layer) { free(layer); } static UA_StatusCode NetworkLayer_FileInput_getBuffer(UA_Connection *connection, UA_ByteString *buf, size_t minSize) { buf->data = malloc(minSize); if(!buf->data) return UA_STATUSCODE_BADOUTOFMEMORY; buf->length = minSize; return UA_STATUSCODE_GOOD; } static void NetworkLayer_FileInput_releaseBuffer(UA_Connection *connection, UA_ByteString *buf) { UA_ByteString_deleteMembers(buf); } UA_ServerNetworkLayer ServerNetworkLayerFileInput_new(UA_UInt32 files, char **filenames, void(*readCallback)(void), UA_StatusCode (*writeCallback) (void*, UA_ByteString *buf), void *callbackHandle) { NetworkLayer_FileInput *layer = malloc(sizeof(NetworkLayer_FileInput)); layer->connection.state = UA_CONNECTION_OPENING; layer->connection.localConf = UA_ConnectionConfig_standard; layer->connection.channel = (void*)0; layer->connection.close = (void (*)(UA_Connection*))closeCallback; layer->connection.write = (UA_StatusCode (*)(UA_Connection*, const UA_ByteString*))writeCallback; layer->connection.releaseBuffer = NetworkLayer_FileInput_releaseBuffer; layer->connection.getBuffer = NetworkLayer_FileInput_getBuffer; layer->files = files; layer->filenames = filenames; layer->files_read = 0; layer->readCallback = readCallback; layer->writeCallback = (UA_StatusCode(*)(struct NetworkLayer_FileInput *handle, const UA_ByteString *buf)) writeCallback; layer->callbackHandle = callbackHandle; UA_ServerNetworkLayer nl; nl.nlHandle = layer; nl.start = (UA_StatusCode (*)(void*, UA_Logger *logger))NetworkLayer_FileInput_start; nl.getWork = (UA_Int32 (*)(void*, UA_WorkItem**, UA_UInt16)) NetworkLayer_FileInput_getWork; nl.stop = (UA_Int32 (*)(void*, UA_WorkItem**)) NetworkLayer_FileInput_stop; nl.free = (void (*)(void*))NetworkLayer_FileInput_delete; nl.discoveryUrl = UA_String_new(); *nl.discoveryUrl = UA_STRING_ALLOC(""); return nl; }