I am writing code to send a Probe message to find my Onvif camera on the network. The message is sent over UDP to a multicast address “239.255.255.250” and UDP port 3702. I have succeeded to connect to the camera and to send the message. However no response from the camera.
The error message is WSA_IO_INCOMPLETE. I have also tryed with INFINITE timeout. What am I missing?
Here is my code:
static int RecvAnswer(SOCKET sfd, WSABUF wsarecvBuf, LPDWORD pNumberOfBytesRecvd) {
int err = 0;
int iResult = 0;
DWORD Flags = 0;
err = 0;
DWORD cTransfer = 0;
//char buf[256];
ZeroMemory(wsarecvBuf.buf, RECV_BUF);
iResult = WSARecv(sfd, &wsarecvBuf, 1, pNumberOfBytesRecvd, &Flags, &RecvOverlapped, NULL);
if (SOCKET_ERROR == iResult) {
err = WSAGetLastError();
if (WSA_IO_PENDING != err) {
std::cout << printf("WSARecv failed with error: %dn", err);
// WSAETIMEDOUT = 1060
return 1;
}
}
iResult = WSAWaitForMultipleEvents(1, &RecvOverlapped.hEvent, TRUE, 10000, TRUE);
if (WSA_WAIT_FAILED == iResult) {
err = WSAGetLastError();
std::cout << printf("WSAWaitForMultipleEvents failed with error: %dn", err);
// WSA_INVALID_HANDLE = 6
return 1;
}
iResult = WSAGetOverlappedResult(sfd, &RecvOverlapped, &cTransfer, FALSE, &Flags);
if (FALSE == iResult) {
err = WSAGetLastError();
std::cout << printf("WSAGetOverlappedResult failed with error: %dn", err);
// WSA_IO_INCOMPLETE = 996
return 1;
}
*pNumberOfBytesRecvd = cTransfer;
WSAResetEvent(RecvOverlapped.hEvent);
return 0;
}
int main() {
int iResult;
char buffer[1024]{};
uint16_t Port = 3702;
const char IpAddress[] = "239.255.255.250";
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR) {
std::cout << "WSAStartup failed to load!n";
system("pause");
return 0;
}
SOCKET sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sfd == INVALID_SOCKET) {
std::cout << "Socket failurn";
system("pause");
return 0;
}
u_long iMode = 0;
iResult = ioctlsocket(sfd, FIONBIO, &iMode);
if (iResult != NO_ERROR) {
closesocket(sfd);
std::cout << "iMode failurn";
system("pause");
return 0;
}
TIMEVAL tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
setsockopt(sfd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(struct timeval));
int optval = RECV_BUF;
int optlen = sizeof(int);
iResult = setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, (char*)&optval, optlen);
if (iResult == SOCKET_ERROR) {
closesocket(sfd);
std::cout << "Set Recieve buffer failurn";
system("pause");
return 0;
}
optval = SEND_BUF;
iResult = setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (char*)&optval, optlen);
if (iResult == SOCKET_ERROR) {
closesocket(sfd);
std::cout << "Set Send buffer failurn";
system("pause");
return 0;
}
sockaddr_in clientService;
SecureZeroMemory(&clientService, sizeof(clientService));
clientService.sin_family = AF_INET;
clientService.sin_port = htons(Port);
inet_pton(AF_INET, IpAddress, &clientService.sin_addr.s_addr);
iResult = connect(sfd, (SOCKADDR*)&clientService, sizeof(clientService));
if (iResult == SOCKET_ERROR) {
int error = WSAGetLastError();
closesocket(sfd);
std::cout << printf("Connect failur. Error code: %dn", error);
system("pause");
return 0;
}
fd_set readfds;
fd_set writefds;
fd_set exceptfds;
tv.tv_sec = 5;
tv.tv_usec = 0;
do {
FD_ZERO(&readfds);
FD_SET(sfd, &readfds);
FD_ZERO(&writefds);
FD_SET(sfd, &writefds);
FD_ZERO(&exceptfds);
FD_SET(sfd, &exceptfds);
iResult = select(0, 0, &writefds, 0, &tv);
} while (iResult == -1 && errno == EINTR);
iResult = __WSAFDIsSet(sfd, &writefds);
if (iResult != 1) {
closesocket(sfd);
std::cout << "Socket could not be includec in descriptorsn";
system("pause");
return 0;
}
optval = 1;
getsockopt(sfd, SOL_SOCKET, SO_ERROR, (char*)&optval, &optlen);
std::cout << "Connectedn";
SecureZeroMemory(&RecvOverlapped, sizeof(WSAOVERLAPPED));
RecvOverlapped.hEvent = WSACreateEvent();
if (RecvOverlapped.hEvent == NULL) {
std::cout << printf("WSACreateEvent failed: %dn", WSAGetLastError());
closesocket(sfd);
return 0;
}
const char* discovery = "<?xml version="1.0" encoding="UTF-8"?>"
"<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://schemas.xmlsoap.org/ws/2004/08/addressing">"
"<soap-env:Header>"
"<a:ReplyTo>"
"<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>"
"</a:ReplyTo>"
"<a:Action a:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>"
"<a:MessageID>uuid:%s</a:MessageID>"
"</soap:Header>"
"<soap-env:Body>"
"<wsd:Probe xmlns="http://schemas.xmlsoap.org/ws/2005/04/discover">"
"<d:Types xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:dp0="http://www.onvif.org/ver10/device/wsdl">"
"tds:Device</d:Types>"
"</d:Probe>"
"</soap-env:Body>"
"</soap-env:Envelope>";
UUID uuid;
RPC_STATUS status = UuidCreate(&uuid);
if (0 != status) {
closesocket(sfd);
std::cout << "Create UUID failedn";
system("pause");
return 0;
}
char* str = nullptr;
status = UuidToStringA(&uuid, (RPC_CSTR*)&str);
if (0 != status) {
closesocket(sfd);
std::cout << "UuidToString failurn";
RpcStringFreeA((RPC_CSTR*)&str);
system("pause");
return 0;
}
WSABUF wsasendBuf;
wsasendBuf.buf = (char*)malloc(SEND_BUF);
wsasendBuf.len = SEND_BUF;
if (!wsasendBuf.buf) {
closesocket(sfd);
std::cout << "Send buffer failedn";
RpcStringFreeA((RPC_CSTR*)&str);
system("pause");
return 0;
}
wsasendBuf.len = sprintf(wsasendBuf.buf, discovery, str);
WSABUF wsarecvBuf;
wsarecvBuf.buf = (char*)malloc(RECV_BUF);
wsarecvBuf.len = RECV_BUF;
if (send(sfd, wsasendBuf.buf, wsasendBuf.len, 0) == SOCKET_ERROR) {
free(wsasendBuf.buf);
free(wsarecvBuf.buf);
closesocket(sfd);
std::cout << "Sending request failedn";
RpcStringFreeA((RPC_CSTR*)&str);
system("pause");
return 0;
}
int NumberOfBytesRecvd = 0;
if (RecvAnswer(sfd, wsarecvBuf, (LPDWORD)&NumberOfBytesRecvd) != 0) {
free(wsasendBuf.buf);
free(wsarecvBuf.buf);
closesocket(sfd);
std::cout << "Recieving answer failedn";
RpcStringFreeA((RPC_CSTR*)&str);
system("pause");
return 0;
}
free(wsasendBuf.buf);
free(wsarecvBuf.buf);
RpcStringFreeA((RPC_CSTR*)&str);
WSACleanup();
closesocket(sfd);
system("pause");
}
Here is the output:
Connected
WSAGetOverlappedResult failed with error: 996
46Recieving answer failed
Press any key to continue . . .
I can’t figure out where 46 comes from. It is printed in connection with the WSAGetOverlappedResult error message.
Does anyone have an idea for a solution.