-
-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
onvif discovery crash in windows #45
Comments
Hi @Viper-Bit , Per the WS-Discovery spec - https://en.wikipedia.org/wiki/WS-Discovery#:~:text=Web%20Services%20Dynamic%20Discovery%20(WS,255.250%20or%20FF02%3A%3AC. "Web Services Dynamic Discovery (WS-Discovery) is a technical specification that defines a multicast discovery protocol to locate services on a local network. It operates over TCP and UDP port 3702 and uses IP multicast address 239.255.255.250 or FF02::C. As the name suggests, the actual communication between nodes is done using web services standards, notably SOAP-over-UDP." Are you running the code on Windows, maybe the Windows firewall is blocking the connection. I don't think this is a code related issue. |
@faithoflifedev thx for answer, |
Thanks for the update @Viper-Bit, I tried the work-arounds suggested in #53477 and none worked for me on Windows 11. Are you able to provide your c++ code and I can look at incorporating it into this package until a better solution is available? |
@faithoflifedev yes OfCourse, onvif.cpp #include "onvif.h"
char preferred_network_address[16];
int setSocketOptions(int socket) {
struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 500000;
int broadcast = 500;
char loopch = 0;
int status = 0;
struct in_addr localInterface;
#ifdef _WIN32
PMIB_IPADDRTABLE pIPAddrTable;
DWORD dwSize = 0;
DWORD dwRetVal = 0;
IN_ADDR IPAddr;
pIPAddrTable = (MIB_IPADDRTABLE*)malloc(sizeof(MIB_IPADDRTABLE));
if (pIPAddrTable) {
if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
free(pIPAddrTable);
pIPAddrTable = (MIB_IPADDRTABLE*)malloc(dwSize);
}
if (pIPAddrTable == NULL) {
printf("Memory allocation failed for GetIpAddrTable\n");
return -1;
}
}
if ((dwRetVal = GetIpAddrTable(pIPAddrTable, &dwSize, 0)) != NO_ERROR) {
printf("GetIpAddrTable failed with error %d\n", dwRetVal);
return -1;
}
int p = 0;
while (p < (int)pIPAddrTable->dwNumEntries) {
IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[p].dwAddr;
IPAddr.S_un.S_addr = (u_long)pIPAddrTable->table[p].dwMask;
if (pIPAddrTable->table[p].dwAddr != inet_addr("127.0.0.1") && pIPAddrTable->table[p].dwMask == inet_addr("255.255.255.0")) {
if (strlen(preferred_network_address) > 0) {
localInterface.s_addr = inet_addr(preferred_network_address);
}
else {
localInterface.s_addr = pIPAddrTable->table[p].dwAddr;
}
status = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&localInterface, sizeof(localInterface));
if (status < 0)
printf("ip_multicast_if error");
p = (int)pIPAddrTable->dwNumEntries;
}
p++;
}
if (pIPAddrTable) {
free(pIPAddrTable);
pIPAddrTable = NULL;
}
status = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&broadcast, sizeof(broadcast));
#else
if (strlen(preferred_network_address) > 0) {
localInterface.s_addr = inet_addr(preferred_network_address);
status = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_IF, (const char*)&localInterface, sizeof(localInterface));
if (status < 0)
printf("ip_multicast_if error");
}
status = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval*)&tv, sizeof(struct timeval));
#endif
status = setsockopt(socket, IPPROTO_IP, IP_MULTICAST_LOOP, (char*)&loopch, sizeof(loopch));
return 0;
}
int discovery(OnvifDiscoveryData* data, const char * probeMessage, int duration) {
#ifdef _WIN32
WSADATA wsaData;
int wsaStartup = WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
sockaddr_in broadcast_address = {};
int broadcast_message_length = strlen(probeMessage);
int broadcast_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setSocketOptions(broadcast_socket);
memset((char*)&broadcast_address, 0, sizeof(broadcast_address));
broadcast_address.sin_family = AF_INET;
broadcast_address.sin_port = htons(3702);
broadcast_address.sin_addr.s_addr = inet_addr("239.255.255.250");
int status = sendto(broadcast_socket, probeMessage, broadcast_message_length, 0, (struct sockaddr*)&broadcast_address, sizeof(broadcast_address));
if (status < 0) {
//error
}
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
int i = 0;
bool loop = true;
socklen_t address_size = sizeof(broadcast_address);
while (loop) {
int len = recvfrom(broadcast_socket, data->buf[i], sizeof(data->buf[i]), 0, (struct sockaddr*)&broadcast_address, &address_size);
if (len > 0) {
i++;
}
else {
loop = false;
if (len < 0) {
//error
}
}
}
#ifdef _WIN32
closesocket(broadcast_socket);
WSACleanup();
#else
close(broadcast_socket);
#endif
return i;
} onvif.h #ifndef ONVIF_H
#define ONVIF_H
#include <chrono>
#include <thread>
#include <cstring>
#ifdef _WIN32
#define LIBRARY_API __declspec(dllexport)
#include <ws2tcpip.h>
#include <iphlpapi.h>
#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "iphlpapi.lib")
#else
#define LIBRARY_API
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#ifdef __MINGW32__
#include <ws2tcpip.h>
#endif
#pragma pack (push, 1)
struct OnvifDiscoveryData {
char buf[128][8192];
};
#pragma pack(pop)
#ifdef __cplusplus
extern "C" {
#endif
LIBRARY_API int discovery(OnvifDiscoveryData* data, const char* probeMessage, int duration);
#ifdef __cplusplus
}
#endif
#endif and dart side is: import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
final Pointer<T> Function<T extends NativeType>(String symbolName) _lookup =
() {
if (Platform.isWindows) {
return DynamicLibrary.open('onvif.dll').lookup;
} else if (Platform.isLinux) {
return DynamicLibrary.open('/usr/local/lib/libonvif.so').lookup;
} else {
throw UnimplementedError();
}
}();
final _discoveryPtr = _lookup<
NativeFunction<
Int32 Function(
Pointer<NativeType>,
Pointer<NativeType>,
Int32,
)>>('discovery');
final _discovery = _discoveryPtr.asFunction<
int Function(
Pointer<NativeType>,
Pointer<NativeType>,
int,
)>();
@Packed(1)
sealed class _OnvifDiscoveryData extends Struct {
@Array<Int8>(128, 8192)
external Array<Array<Int8>> buf;
}
const _probeMessage = '''
<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:Action SOAP-ENV:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</a:Action>
<a:MessageID>urn:uuid:2809d092-cb6c-476a-9a6f-7ee0123265d3</a:MessageID>
<a:ReplyTo>
<a:Address>http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</a:Address>
</a:ReplyTo>
<a:To SOAP-ENV:mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<p:Probe xmlns:p="http://schemas.xmlsoap.org/ws/2005/04/discovery">
<d:Types xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:dp0="http://www.onvif.org/ver10/network/wsdl">dp0:NetworkVideoTransmitter</d:Types>
</p:Probe>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
''';
Future<void> discovery([Duration duration = const Duration(seconds: 5)]) async {
final data = calloc<_OnvifDiscoveryData>();
final probeMessageData = _probeMessage.toNativeUtf8();
final devices = _discovery(data, probeMessageData, duration.inMilliseconds);
//for flutter _discovery cant be called in main thread (locks main thread for duration) so _discovery must be called from isolate
/*
final devices = await compute(
(msg) {
return _discovery(
Pointer.fromAddress(msg['dataAddress'] as int),
Pointer.fromAddress(msg['probeAddress'] as int),
msg['duration'] as int,
);
},
{
'dataAddress': data.address,
'probeAddress': probeMessageData.address,
'duration': duration.inMilliseconds,
},
);
*/
print('Found $devices Devices');
for (var index = 0; index < devices; index++) {
print(Pointer.fromAddress(data.address + index * 8192)
.cast<Utf8>()
.toDartString());
}
malloc.free(probeMessageData);
calloc.free(data);
} |
Hi @Viper-Bit , as an update on this, I'm currently readying a new release with the above workaround for Windows OS included. It should be available in a day or two. Thanks for your help with this. |
Hi @Viper-Bit , I've just published the new package v2.1.3+1. Please let me know if this resolves the issue for you, or if you need a better explanation on how to use the fix (see the |
hi, i use this code for device descovery:
but when i run it my program crashs with bellow error
The text was updated successfully, but these errors were encountered: