I wrote a dll in C++ which allows me to perform Winsock functions from PowerBuilder code.
For IPv4 it works great but I am getting an error in IPv6. I am starting with the UDP functions because they are simpler. The following error occurs on the sendto:
The requested address is not valid in its context
In the below code, ud.family will either be set to AF_INET or AF_NET6.
What I have tried:
PBXRESULT winsock::fn_sendto_u(PBCallInfo * ci)
{
PBXRESULT pbxr = PBX_OK;
SOCKET SendSocket = INVALID_SOCKET;
sockaddr_in SendAddr4;
sockaddr_in6 SendAddr6;
USHORT port;
int iResult = 0;
LPCTSTR lpHostName = NULL;
LPCTSTR lpMessage = NULL;
int nBytes = 0, nLeft = 0, idx = 0;
pbstring arg0 = ci->pArgs->GetAt(0)->GetString();
lpHostName = ud.session->GetString(arg0);
port = ci->pArgs->GetAt(1)->GetUint();
pbstring arg2 = ci->pArgs->GetAt(2)->GetString();
lpMessage = ud.session->GetString(arg2);
nBytes = (int) _tcslen(lpMessage) * sizeof(TCHAR);
SendSocket = socket(ud.family, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET) {
ci->returnValue->SetBool(FALSE);
return pbxr;
}
switch(ud.family) {
case AF_INET:
SendAddr4.sin_family = AF_INET;
SendAddr4.sin_port = htons(port);
InetPtonW(AF_INET, lpHostName, &SendAddr4.sin_addr);
break;
case AF_INET6:
SendAddr6.sin6_family = AF_INET6;
SendAddr6.sin6_port = htons(port);
InetPtonW(AF_INET6, lpHostName, &SendAddr6.sin6_addr);
break;
}
nLeft = nBytes;
while (nLeft > 0) {
switch(ud.family) {
case AF_INET:
iResult = sendto(SendSocket, (char*) lpMessage + idx, (int) nLeft, 0,
(SOCKADDR *) &SendAddr4, sizeof(SendAddr4));
break;
case AF_INET6:
iResult = sendto(SendSocket, (char*) lpMessage + idx, (int) nLeft, 0,
(SOCKADDR *) &SendAddr6, sizeof(SendAddr6));
break;
}
if (iResult == SOCKET_ERROR) {
iResult = WSAGetLastError();
closesocket(SendSocket);
WSASetLastError(iResult);
ci->returnValue->SetBool(FALSE);
return pbxr;
}
nLeft -= iResult;
idx += iResult;
}
closesocket(SendSocket);
ci->returnValue->SetBool(TRUE);
return pbxr;
}