static int CallMpi()

in src/common/mpiclient/MpiClient.c [24:159]


static int CallMpi(const char* name, const char* request, char** response, int* responseSize, OsConfigLogHandle log)
{
    const char* mpiSocket = "/run/osconfig/mpid.sock";
    const char* dataFormat = "POST /%s/ HTTP/1.1\r\nHost: OSConfig\r\nUser-Agent: OSConfig\r\nAccept: */*\r\nContent-Type: application/json\r\nContent-Length: %d\r\n\r\n%s";

    int socketHandle = -1;
    char* data = {0};
    int estimatedDataSize = 0;
    int actualDataSize = 0;
    char contentLengthString[MPI_MAX_CONTENT_LENGTH] = {0};
    struct sockaddr_un socketAddress = {0};
    socklen_t socketLength = 0;
    ssize_t bytes = 0;
    int status = MPI_OK;
    int httpStatus = -1;

    if ((NULL == name) || (NULL == request) || (NULL == response) || (NULL == responseSize))
    {
        status = EINVAL;
        OsConfigLogError(log, "CallMpi(%s): invalid arguments (%d)", name, status);
        return status;
    }

    *response = NULL;
    *responseSize = 0;

    if (0 != (status = CheckFileAccess(mpiSocket, 0, 0, 06770, NULL, IsDebugLoggingEnabled() ? log : NULL)))
    {
        if (0 != (status = SetFileAccess(mpiSocket, 0, 0, 06770, IsDebugLoggingEnabled() ? log : NULL)))
        {
            OsConfigLogError(log, "CallMpi(%s): access to the MPI socket is not protected, cannot call the MPI (%d)", name, status);
            return status;
        }
    }

    snprintf(contentLengthString, sizeof(contentLengthString), "%d", (int)strlen(request));
    estimatedDataSize = strlen(name) + strlen(dataFormat) + strlen(request) + strlen(contentLengthString) + 1;

    data = (char*)malloc(estimatedDataSize);
    if (NULL == data)
    {
        status = ENOMEM;
        OsConfigLogError(log, "CallMpi(%s): failed to allocate memory for request (%d)", name, status);
        return status;
    }

    memset(data, 0, estimatedDataSize);

    socketHandle = socket(AF_UNIX, SOCK_STREAM, 0);
    if (0 > socketHandle)
    {
        status = errno ? errno : EIO;
        OsConfigLogError(log, "CallMpi(%s): failed to open socket '%s' (%d)", name, mpiSocket, status);
    }
    else
    {
        memset(&socketAddress, 0, sizeof(socketAddress));
        socketAddress.sun_family = AF_UNIX;
        strncpy(socketAddress.sun_path, mpiSocket, sizeof(socketAddress.sun_path) - 1);
        socketLength = sizeof(socketAddress);
    }

    if (MPI_OK == status)
    {
        if (0 == connect(socketHandle, (struct sockaddr*)&socketAddress, socketLength))
        {
            snprintf(data, estimatedDataSize, dataFormat, name, strlen(request), request);
            actualDataSize = (int)strlen(data);
        }
        else
        {
            status = errno ? errno : EIO;
            OsConfigLogError(log, "CallMpi(%s): failed to connect to socket '%s' (%d)", name, mpiSocket, status);
        }
    }

    if (MPI_OK == status)
    {
        bytes = send(socketHandle, data, actualDataSize, 0);
        if (bytes != actualDataSize)
        {
            status = errno ? errno : EIO;
            if (IsDebugLoggingEnabled())
            {
                OsConfigLogError(log, "CallMpi(%s): failed to send request '%s' (%d bytes) to socket '%s' (%d)", name, data, actualDataSize, mpiSocket, status);
            }
            else
            {
                OsConfigLogError(log, "CallMpi(%s): failed to send request to socket '%s' of %d bytes (%d)", name, mpiSocket, actualDataSize, status);
            }
        }
        else
        {
            OsConfigLogDebug(log, "CallMpi(%s): sent to '%s' '%s' (%d bytes)", name, mpiSocket, data, actualDataSize);
        }
    }

    FREE_MEMORY(data);

    if (MPI_OK == status)
    {
        httpStatus = ReadHttpStatusFromSocket(socketHandle, log);
        status = (200 == httpStatus) ? MPI_OK : httpStatus;

        *responseSize = ReadHttpContentLengthFromSocket(socketHandle, log);
        *response = (char*)malloc(*responseSize + 1);
        if (NULL != *response)
        {
            memset(*response, 0, *responseSize + 1);

            if (*responseSize != read(socketHandle, *response, *responseSize))
            {
                if ((MPI_OK == status) || IsDebugLoggingEnabled())
                {
                    OsConfigLogError(log, "CallMpi(%s): failed to read %d bytes response from socket '%s' (%d)", name, *responseSize, mpiSocket, status);
                }
                status = errno ? errno : EIO;
            }
        }
        else
        {
            status = ENOMEM;
            *responseSize = 0;
            OsConfigLogError(log, "CallMpi(%s): failed to allocate memory for response (%d)", name, status);
        }
    }

    if (0 <= socketHandle)
    {
        close(socketHandle);
    }

    OsConfigLogDebug(log, "CallMpi(name: '%s', request: '%s', response: '%s', response size: %d bytes) to socket '%s' returned %d", name, request, *response, *responseSize, mpiSocket, status);

    return status;
}