/*============================================================================
 * OpcUa_P_ParseUrl
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_ParseUrl(  OpcUa_StringA   a_psUrl,
                                    OpcUa_StringA*  a_psIpAdress,
                                    OpcUa_UInt16*   a_puPort)
{
    OpcUa_UInt32    uUrlLength        = 0;

    OpcUa_StringA   sHostName         = OpcUa_Null;
    OpcUa_UInt32    uHostNameLength   = 0;

    OpcUa_CharA*    pcCursor          = OpcUa_Null;

    OpcUa_Int       nIndex1           = 0;
    OpcUa_Int       nIpStart          = 0;

    struct hostent* pHostEnt          = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_Utilities, "P_ParseUrl");

    OpcUa_ReturnErrorIfArgumentNull(a_psUrl);
    OpcUa_ReturnErrorIfArgumentNull(a_psIpAdress);
    OpcUa_ReturnErrorIfArgumentNull(a_puPort);

    *a_psIpAdress = OpcUa_Null;

    uUrlLength = (OpcUa_UInt32)strlen(a_psUrl);

    /* check for // (end of protocol header) */
    pcCursor = strstr(a_psUrl, "//");

    if(pcCursor != OpcUa_Null)
    {
        /* begin of host address */
        pcCursor += 2;
        nIndex1 = (OpcUa_Int)(pcCursor - a_psUrl);
    }
    else
    {
        uStatus = OpcUa_BadSyntaxError;
        OpcUa_ReturnStatusCode;
    }

    /* skip protocol prefix and store beginning of ip adress */
    nIpStart = nIndex1;

    /* skip host address */
    while(      a_psUrl[nIndex1] != ':'
            &&  a_psUrl[nIndex1] != '/'
            &&  a_psUrl[nIndex1] != 0
            &&  nIndex1          <  (OpcUa_Int32)uUrlLength)
    {
        nIndex1++;
    }

    uHostNameLength = nIndex1 - nIpStart;
    sHostName       = (OpcUa_StringA)malloc(uHostNameLength + 1);
    if(sHostName == NULL)
    {
        return OpcUa_BadOutOfMemory;
    }

    memcpy(sHostName, &a_psUrl[nIpStart], uHostNameLength);
    sHostName[uHostNameLength] = '\0';

    pHostEnt = gethostbyname(sHostName);

    free(sHostName);

    if(pHostEnt == NULL)
    {
        /* hostname could not be resolved */
        return OpcUa_BadHostUnknown;
    }

    nIpStart = 0;
    *a_psIpAdress = (OpcUa_StringA)OpcUa_P_Memory_Alloc(16);
    memset(*a_psIpAdress, 0, 16);

#if OPCUA_USE_SAFE_FUNCTIONS
    nIpStart += sprintf_s(&(*a_psIpAdress)[0],         16,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[0]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart],  12,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[1]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart],   8,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[2]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf_s(&(*a_psIpAdress)[nIpStart],   4,"%u", (unsigned char)(*((*pHostEnt).h_addr_list))[3]);
#else /* OPCUA_USE_SAFE_FUNCTIONS */

    nIpStart += sprintf(&(*a_psIpAdress)[0], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[0]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[1]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[2]);
    (*a_psIpAdress)[nIpStart++] = '.';
    nIpStart += sprintf(&(*a_psIpAdress)[nIpStart], "%u", (unsigned char)(*((*pHostEnt).h_addr_list))[3]);
#endif /* OPCUA_USE_SAFE_FUNCTIONS */

    /* scan port */
    if(a_psUrl[nIndex1] == ':')
    {
        OpcUa_Int       nIndex2 = 0;
        OpcUa_CharA*    sPort   = OpcUa_Null;
        OpcUa_CharA sBuffer[MAX_PORT_LENGTH];

        /* skip delimiter */
        nIndex1++;

        /* store beginning of port */
        sPort = &a_psUrl[nIndex1];

        /* search for end of port */
        while(      a_psUrl[nIndex1] != '/'
                &&  a_psUrl[nIndex1] != 0
                &&  nIndex2          <  6)
        {
            nIndex1++;
            nIndex2++;
        }

        /* convert port */
        OpcUa_P_Memory_MemCpy(sBuffer, MAX_PORT_LENGTH-1, sPort, nIndex2);
        sBuffer[nIndex2] = 0;
        *a_puPort = (OpcUa_UInt16)OpcUa_P_CharAToInt(sBuffer);
    }
    else
    {
        /* return default port */
        if (strncmp(a_psUrl, "http:", 5) != 0)
        {
            *a_puPort = OPCUA_TCP_DEFAULT_PORT;
        }
        else
        {
            *a_puPort = OPCUA_HTTP_DEFAULT_PORT;
        }
    }

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;
OpcUa_FinishErrorHandling;
}
Example #2
0
/*============================================================================
 * OpcUa_P_ParseUrl
 *===========================================================================*/
OpcUa_StatusCode OpcUa_P_ParseUrl(  OpcUa_StringA   a_psUrl,
                                    OpcUa_StringA*  a_psIpAddress,
                                    OpcUa_UInt16*   a_puPort)
{
    OpcUa_StringA       sHostName         = OpcUa_Null;
    OpcUa_UInt32        uHostNameLength   = 0;

    OpcUa_CharA*        sPort             = OpcUa_Null;

    OpcUa_CharA*        pcCursor;

    OpcUa_Int           nIndex1           = 0;
    OpcUa_Int           nIpStart;

    struct addrinfo*    pAddrInfo         = OpcUa_Null;

OpcUa_InitializeStatus(OpcUa_Module_Utilities, "P_ParseUrl");

    OpcUa_ReturnErrorIfArgumentNull(a_psUrl);
    OpcUa_ReturnErrorIfArgumentNull(a_psIpAddress);
    OpcUa_ReturnErrorIfArgumentNull(a_puPort);


    *a_psIpAddress = OpcUa_Null;

    /* check for // (end of protocol header) */
    pcCursor = strstr(a_psUrl, "//");

    if(pcCursor != OpcUa_Null)
    {
        /* begin of host address */
        pcCursor += 2;
        nIndex1 = (OpcUa_Int)(pcCursor - a_psUrl);
    }

    /* skip protocol prefix and store beginning of ip adress */
    nIpStart = nIndex1;

    /* skip host address (IPv6 address can contain colons!) */
    while(a_psUrl[nIndex1] != '/' && a_psUrl[nIndex1] != 0)
    {
        if(a_psUrl[nIndex1] == ':')
        {
            sPort = &a_psUrl[nIndex1 + 1];
            uHostNameLength = nIndex1 - nIpStart;
        }
        /* handle "opc.tcp://[::1]:4880/" */
        if(a_psUrl[nIndex1] == ']' && sPort != OpcUa_Null && a_psUrl[nIpStart] == '[')
        {
            nIpStart++;
            uHostNameLength = nIndex1 - nIpStart;
            sPort = OpcUa_Null;
            if(a_psUrl[nIndex1 + 1] == ':')
            {
                sPort = &a_psUrl[nIndex1 + 2];
            }
            break;
        }
        nIndex1++;
    }

    if(uHostNameLength == 0)
    {
        uHostNameLength = nIndex1 - nIpStart;
    }

    /* scan port */
    if(sPort != OpcUa_Null)
    {
        /* convert port */
        *a_puPort = (OpcUa_UInt16)OpcUa_P_CharAToInt(sPort);
    }
    else
    {
        /* return default port */
        *a_puPort = OPCUA_TCP_DEFAULT_PORT;
    }

    sHostName = (OpcUa_StringA)OpcUa_P_Memory_Alloc(uHostNameLength + 1);

    if(sHostName == NULL)
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadOutOfMemory);
    }

    memcpy(sHostName, &a_psUrl[nIpStart], uHostNameLength);
    sHostName[uHostNameLength] = '\0';

    if(getaddrinfo(sHostName, NULL, NULL, &pAddrInfo))
    {
        /* hostname could not be resolved */
        pAddrInfo = NULL;
        OpcUa_GotoErrorWithStatus(OpcUa_BadHostUnknown);
    }

    if(pAddrInfo->ai_family == AF_INET)
    {
        struct sockaddr_in* pAddr = (struct sockaddr_in*)pAddrInfo->ai_addr;
        OpcUa_P_Memory_Free(sHostName);
        sHostName = OpcUa_P_Memory_Alloc(INET_ADDRSTRLEN);
        OpcUa_GotoErrorIfAllocFailed(sHostName);
        if(inet_ntop(AF_INET, (void*)&pAddr->sin_addr,
                     sHostName, INET_ADDRSTRLEN) == NULL)
        {
            OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);
        }
    }
    else if(pAddrInfo->ai_family == AF_INET6)
    {
        struct sockaddr_in6* pAddr = (struct sockaddr_in6*)pAddrInfo->ai_addr;
        OpcUa_P_Memory_Free(sHostName);
        sHostName = OpcUa_P_Memory_Alloc(INET6_ADDRSTRLEN);
        OpcUa_GotoErrorIfAllocFailed(sHostName);
        if(inet_ntop(AF_INET6, (void*)&pAddr->sin6_addr,
                     sHostName, INET6_ADDRSTRLEN) == NULL)
        {
            OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);
        }
        if(pAddr->sin6_scope_id)
        {
            char *pScopeAddress = OpcUa_P_Memory_Alloc(strlen(sHostName) + 12);
            OpcUa_GotoErrorIfAllocFailed(pScopeAddress);
            sprintf(pScopeAddress, "%s%%%u", sHostName, pAddr->sin6_scope_id);
            OpcUa_P_Memory_Free(sHostName);
            sHostName = pScopeAddress;
        }
    }
    else
    {
        OpcUa_GotoErrorWithStatus(OpcUa_BadInternalError);
    }

    *a_psIpAddress = sHostName;
    freeaddrinfo(pAddrInfo);

OpcUa_ReturnStatusCode;
OpcUa_BeginErrorHandling;

    if(sHostName != OpcUa_Null)
    {
        OpcUa_P_Memory_Free(sHostName);
    }

    if(pAddrInfo != NULL)
    {
        freeaddrinfo(pAddrInfo);
    }

OpcUa_FinishErrorHandling;
}