/*---------------------------------------------------------------------- | PLT_SsdpDeviceSearchResponseInterfaceIterator class +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpDeviceSearchResponseInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const { const NPT_SocketAddress* remote_addr = &m_RemoteAddr; NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = net_if->GetAddresses().GetFirstItem(); if (!niaddr) return NPT_SUCCESS; // don't try to bind on port 1900 or connect will fail later NPT_UdpSocket socket; //socket.Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900), true); // by connecting, the kernel chooses which interface to use to route to the remote // this is the IP we should use in our Location URL header NPT_CHECK_WARNING(socket.Connect(m_RemoteAddr, 5000)); NPT_SocketInfo info; socket.GetInfo(info); // did we successfully connect and found out which interface is used? if (info.local_address.GetIpAddress().AsLong()) { // check that the interface the kernel chose matches the interface // we wanted to send on if ((*niaddr).GetPrimaryAddress().AsLong() != info.local_address.GetIpAddress().AsLong()) { return NPT_SUCCESS; } // socket already connected, so we don't need to specify where to go remote_addr = NULL; } NPT_HttpResponse response(200, "OK", NPT_HTTP_PROTOCOL_1_1); PLT_UPnPMessageHelper::SetLocation(response, m_Device->GetDescriptionUrl(info.local_address.GetIpAddress().ToString())); PLT_UPnPMessageHelper::SetLeaseTime(response, m_Device->GetLeaseTime()); PLT_UPnPMessageHelper::SetServer(response, PLT_HTTP_DEFAULT_SERVER, false); response.GetHeaders().SetHeader("EXT", ""); // process search response twice to be DLNA compliant #if defined(PLATINUM_UPNP_SPECS_STRICT) { //NPT_UdpSocket socket; NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); } NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY_GROUP)); #endif { //NPT_UdpSocket socket; NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_SsdpDeviceSearchResponseInterfaceIterator class +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpDeviceSearchResponseInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const { NPT_Result res; const NPT_SocketAddress* remote_addr = &m_RemoteAddr; NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = net_if->GetAddresses().GetFirstItem(); if (!niaddr) return NPT_SUCCESS; NPT_UdpSocket socket; // by connecting, the kernel chooses which interface to use to route to the remote // this is the IP we should use in our Location URL header if (NPT_FAILED(res = socket.Connect(m_RemoteAddr, 5000))) { return res; } NPT_SocketInfo info; socket.GetInfo(info); // did we successfully connect and found out which interface is used? if (info.local_address.GetIpAddress().AsLong()) { // check that the interface the kernel chose matches the interface // we wanted to send on if ((*niaddr).GetPrimaryAddress().AsLong() != info.local_address.GetIpAddress().AsLong()) { return NPT_SUCCESS; } // socket already connected, so we don't need to specify where to go remote_addr = NULL; } NPT_HttpResponse response(200, "OK", NPT_HTTP_PROTOCOL_1_1); PLT_UPnPMessageHelper::SetLocation(response, m_Device->GetDescriptionUrl((*niaddr).GetPrimaryAddress().ToString())); PLT_UPnPMessageHelper::SetLeaseTime(response, (NPT_Timeout)((float)m_Device->GetLeaseTime())); PLT_UPnPMessageHelper::SetServer(response, NPT_HttpServer::m_ServerHeader, false); response.GetHeaders().SetHeader("EXT", ""); // process search response twice to be NMPR compliant NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_SsdpDeviceSearchResponseInterfaceIterator class +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpDeviceSearchResponseInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const { NPT_Result res; const NPT_SocketAddress* remote_addr = &m_RemoteAddr; NPT_List<NPT_NetworkInterfaceAddress>::Iterator netaddr = net_if->GetAddresses().GetFirstItem(); if (!netaddr) { return NPT_SUCCESS; } // don't respond on loopback // windows media player on vista sends it's M-SEARCH to loopback interface if it's a local clients sometimes //if (net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) { // return NPT_SUCCESS; //} NPT_SocketAddress local_addr((*netaddr).GetPrimaryAddress(), 0); // 1900? NPT_UdpSocket socket; //if (NPT_FAILED(res = socket.Bind(local_addr))) { // return res; //} // get the output socket stream NPT_OutputStreamReference stream; if (NPT_FAILED(res = socket.GetOutputStream(stream))) { return res; } NPT_HttpResponse response(200, "OK", NPT_HTTP_PROTOCOL_1_1); // get location URL based on ip address of interface // by connecting, the kernel chooses which interface to use to route to the remote // this is the IP we should use in our Location if (NPT_FAILED(res = socket.Connect(m_RemoteAddr, 5000))) { return res; } NPT_SocketInfo info; socket.GetInfo(info); // did we successfully connect and found out which interface is used? if (info.local_address.GetIpAddress().AsLong()) { // check that the interface the kernel chose matches the interface // we wanted to send on // FIXME: Should we fail instead and stop sending a response once we get NPT_SUCCESS? if (local_addr.GetIpAddress().AsLong() != info.local_address.GetIpAddress().AsLong()) { return NPT_SUCCESS; } // already connected, so we don't need to specify where to go remote_addr = NULL; } PLT_UPnPMessageHelper::SetLocation(response, m_Device->GetDescriptionUrl(local_addr.GetIpAddress().ToString())); PLT_UPnPMessageHelper::SetLeaseTime(response, (NPT_Timeout)((float)m_Device->GetLeaseTime())); PLT_UPnPMessageHelper::SetServer(response, "UPnP/1.0, Platinum UPnP SDK/" PLT_PLATINUM_VERSION_STRING, false); response.GetHeaders().SetHeader("EXT", ""); // process search response twice to be NMPR compliant NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); NPT_CHECK_SEVERE(m_Device->SendSsdpSearchResponse(response, socket, m_ST, remote_addr)); return NPT_SUCCESS; }