Я разрабатываю приложение ONVIF для IP-камеры NVT (Network Video Transmitter).
Для обнаружения устройств ONVIF использует спецификации Ws-discovery. Обнаружение использует многоадресный UDP-сокет для отправки приветственного сообщения в начале выполнения программного обеспечения.
когда я наблюдаю за сетью с помощью wireshark, я вижу свой UDP-запрос с правильным портом (3702) в «dst port», но «src port» является случайным значением.
Можно ли изменить порт src моего сокета, используя gSOAP, и использовать его для источника и назначения.
Мой код для отправки приветственного сообщения:
unsigned int localIp = 0;
string interface("eth0");
char type[256];
char port[256];
interface = getNetworkInterface();
netGetIp((char*)interface.c_str(), &localIp);
struct soap *soap = soap_new1(SOAP_IO_UDP | SO_BROADCAST);
soap_init2(soap, SOAP_IO_UDP|SOAP_XML_IGNORENS|SO_BROADCAST, SOAP_IO_UDP|SOAP_XML_IGNORENS|SO_BROADCAST);
soap_bind(soap, NULL, 3702, 100);
ip_mreq multicastRequest;
multicastRequest.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
multicastRequest.imr_interface.s_addr = htonl(localIp);
setsockopt(soap->master, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*) &multicastRequest, sizeof(multicastRequest));
soap->header = soap_new_SOAP_ENV__Header(soap);
soap_default_SOAP_ENV__Header(soap, soap->header);
soap->header->wsa__MessageID = (char *) soap_malloc(soap,strlen(m_uuid.c_str())+1);
strcpy(soap->header->wsa__MessageID, m_uuid.c_str());
string to_str = "urn:schemas-xmlsoap-org:ws:2005:04:discovery";
soap->header->wsa__To = (char *) soap_malloc(soap,strlen(to_str.c_str())+1);
strcpy(soap->header->wsa__To, to_str.c_str());
soap->header->wsa__RelatesTo = soap_new_wsa__Relationship(soap);
soap->header->wsa__RelatesTo->__item = to_str;
char action[64];
strcpy(action, SOAP_NAMESPACE_OF_wsdd);
strcat(action, "/Hello");
soap->header->wsa__Action = (char *) soap_malloc(soap,strlen(action)+1);
strcpy(soap->header->wsa__Action, action);
soap->header->wsa__ReplyTo = soap_new_wsa__EndpointReferenceType(soap);
soap->header->wsa__ReplyTo->Address = soap_new_wsa__AttributedURI(soap);
soap->header->wsa__ReplyTo->Address->__item = "http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";
soap->header->wsdd__AppSequence = soap_new_wsdd__AppSequenceType(soap);
soap->header->wsdd__AppSequence->InstanceId = 0;
soap->header->wsdd__AppSequence->MessageNumber = 1;
soap->header->wsa5__Action = NULL;
soap->header->wsa5__FaultTo = NULL;
soap->header->wsa5__From = NULL;
soap->header->wsa5__MessageID = NULL;
soap->header->wsa5__RelatesTo = NULL;
soap->header->wsa5__ReplyTo = NULL;
soap->header->wsa5__To = NULL;
soap->header->chan__ChannelInstance = NULL;
soap->header->wsa__FaultTo = NULL;
soap->header->wsa__From = NULL;
string endpoint_str = "soap.udp://239.255.255.250:3702";
strcpy(soap->endpoint, endpoint_str.c_str());
char szDevXAddr[256];
strcpy((char*)type,"dn:NetworkVideoTransmitter tds:Device");
sprintf(port, "%d", getDeviceServicePort());
sprintf(szDevXAddr, "http://%s:%s/onvif/device_service", inet_ntoa(*((struct in_addr *)&localIp)),port);
struct __dn__Hello *soap_tmp___dn__Hello = soap_new___dn__Hello(soap);
soap_tmp___dn__Hello->dn__Hello = soap_new_wsdd__HelloType(soap);
soap_tmp___dn__Hello->dn__Hello->Scopes = soap_new_wsdd__ScopesType(soap);
soap_tmp___dn__Hello->dn__Hello->Scopes->__item.assign(getScopesStr().c_str());
soap_tmp___dn__Hello->dn__Hello->Scopes->MatchBy = NULL;
soap_tmp___dn__Hello->dn__Hello->XAddrs = soap_new_std__string(soap);
soap_tmp___dn__Hello->dn__Hello->XAddrs->assign(szDevXAddr);
soap_tmp___dn__Hello->dn__Hello->Types = soap_new_std__string(soap);
soap_tmp___dn__Hello->dn__Hello->Types->assign(type);
string addresse = "urn:" + m_uuid;
soap_tmp___dn__Hello->dn__Hello->wsa__EndpointReference = soap_new_wsa__EndpointReferenceType(soap);
soap_tmp___dn__Hello->dn__Hello->wsa__EndpointReference->Address = soap_new_wsa__AttributedURI(soap);
soap_tmp___dn__Hello->dn__Hello->wsa__EndpointReference->Address->__item = addresse;
soap_tmp___dn__Hello->dn__Hello->wsa__EndpointReference->Address->soap = soap;
static const struct Namespace namespaces[] =
{
{"SOAP-ENV", "http://www.w3.org/2003/05/soap-envelope", "http://schemas.xmlsoap.org/soap/envelope/", NULL},
{"wsa", "http://schemas.xmlsoap.org/ws/2004/08/addressing", NULL, NULL},
{"wsdd", "http://schemas.xmlsoap.org/ws/2005/04/discovery", NULL, NULL},
{"dn", "http://www.onvif.org/ver10/network/wsdl", NULL, NULL},
{"tds", "http://www.onvif.org/ver10/device/wsdl", NULL, NULL},
{"tt", "http://www.onvif.org/ver10/schema", NULL, NULL},
{NULL, NULL, NULL, NULL}
};
soap_set_namespaces(soap, namespaces);
soap_set_local_namespaces(soap);
soap->encodingStyle = NULL;
soap_begin(soap);
soap_serializeheader(soap);
if (soap_begin_count(soap))
return;
soap_connect(soap, soap_url(soap, endpoint_str.c_str(), NULL), "http://docs.oasis-open.org/ws-dd/ns/discovery/2009/01/Hello");
soap_envelope_begin_out(soap);
soap_putheader(soap);
soap_body_begin_out(soap);
soap_tmp___dn__Hello->dn__Hello->soap_put(soap, "wsdd:Hello", NULL);
soap_body_end_out(soap);
soap_envelope_end_out(soap);
soap_end_send(soap);
soap_end(soap);
soap_free(soap);
Задача ещё не решена.
Других решений пока нет …