mz-automation / libiec61850

Official repository for libIEC61850, the open-source library for the IEC 61850 protocols
http://libiec61850.com/libiec61850
GNU General Public License v3.0
828 stars 444 forks source link

MmsValue_encode/decodeMmsData fails on Visible String attribute with empty payload #506

Open rauschenbergerjanos-prolan opened 1 month ago

rauschenbergerjanos-prolan commented 1 month ago

The titular pair of functions fails to serialize or deserialize a visible string data attribute with an empty payload ""; non-empty payloads are seemingly fine.

One of the server examples below edited to display the issue:

 *  server_example_dynamic.c
 *
 *  This example shows how to build a data model at runtime by API calls.
 *
 */

#include "iec61850_server.h"
#include "hal_thread.h"
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>

static int running = 0;

void sigint_handler(int signalId)
{
    running = 0;
}

int main(int argc, char** argv) {

    int tcpPort = 102;

    if (argc > 1) {
        tcpPort = atoi(argv[1]);
    }

    IedModel* model = IedModel_create("testmodel");
    LogicalDevice* lDevice1 = LogicalDevice_create("LD1", model);
    LogicalNode* lln0 = LogicalNode_create("LLN0", lDevice1);
    DataObject* info = CDC_VSS_create("Info", (ModelNode*) lln0, 0);

    SettingGroupControlBlock_create(lln0, 1, 1);

    IedServer iedServer = IedServer_create(model);

    /* MMS server will be instructed to start listening to client connections. */
    IedServer_start(iedServer, tcpPort);

    if (!IedServer_isRunning(iedServer)) {
        printf("Starting server failed! Exit.\n");
        IedServer_destroy(iedServer);
        exit(-1);
    }

    running = 1;

    signal(SIGINT, sigint_handler);

    while (running) {
        IedServer_lockDataModel(iedServer);

        ModelNode *info = IedModel_getModelNodeByShortObjectReference(model, "LD1/LLN0.Info.stVal");
        assert(info && ModelNode_getType(info) == DataAttributeModelType);

        IedServer_updateVisibleStringAttributeValue(iedServer, (DataAttribute *)info, "Hello, World!");

        char buf[512] = {0};
        size_t s = MmsValue_encodeMmsData(((DataAttribute *)info)->mmsValue, buf, 0, true);
        assert(s != 0);

        MmsValue *value = MmsValue_decodeMmsData(buf, 0, s, NULL);

        if(value)
            printf("Non-empty String data attribute succesfully loaded\n");
        else
            exit(1);

        IedServer_updateVisibleStringAttributeValue(iedServer, (DataAttribute *)info, "");
        s = MmsValue_encodeMmsData(((DataAttribute *)info)->mmsValue, buf, 0, true);
        assert(s != 0);

       if(!MmsValue_decodeMmsData(buf, 0, s, NULL)) {
            printf("Empty string data attribute could not be loaded\n");
            exit(1);
        }

        IedServer_unlockDataModel(iedServer);
    }

    IedServer_stop(iedServer);
    IedServer_destroy(iedServer);
    IedModel_destroy(model);

    return 0;
} /* main() */