/*============================================================================ * 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; }
/*============================================================================ * 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; }