/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | GetEndPointStreams +---------------------------------------------------------------------*/ static NPT_Result GetEndPointStreams(EndPoint* endpoint, NPT_InputStreamReference* input_stream, NPT_OutputStreamReference* output_stream) { // default return values if (input_stream) *input_stream = NULL; if (output_stream) *output_stream = NULL; switch (endpoint->type) { case ENDPOINT_TYPE_UDP_CLIENT: { NPT_UdpSocket sender; // info if (Options.verbose) { NPT_Debug("sending to %s on port %d\n", endpoint->info.udp_client.hostname, endpoint->info.udp_client.port); } // resolve name NPT_IpAddress address; NPT_CHECK(address.ResolveName(endpoint->info.udp_client.hostname)); // connect socket NPT_CHECK(sender.Connect(NPT_SocketAddress(address, endpoint->info.udp_client.port))); // get the streams if (input_stream) { NPT_CHECK(sender.GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(sender.GetOutputStream(*output_stream)); } return NPT_SUCCESS; } break; case ENDPOINT_TYPE_TCP_CLIENT: { NPT_TcpClientSocket client; // info if (Options.verbose) { NPT_Debug("connecting to %s on port %d\n", endpoint->info.tcp_client.hostname, endpoint->info.tcp_client.port); } // resolve the name NPT_IpAddress address; NPT_CHECK(address.ResolveName(endpoint->info.tcp_client.hostname)); // connect NPT_CHECK(client.Connect(NPT_SocketAddress(address, endpoint->info.tcp_client.port))); // info if (Options.verbose) { NPT_Debug("connected\n"); } // get the streams if (input_stream) { NPT_CHECK(client.GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(client.GetOutputStream(*output_stream)); } return NPT_SUCCESS; } break; case ENDPOINT_TYPE_MULTICAST_CLIENT: { NPT_UdpMulticastSocket sender; // info if (Options.verbose) { NPT_Debug("sending to %s on port %d\n", endpoint->info.multicast_client.groupname, endpoint->info.multicast_client.port); } // set time to live NPT_CHECK(sender.SetTimeToLive(endpoint->info.multicast_client.ttl)); // resolve name NPT_IpAddress address; NPT_CHECK(address.ResolveName(endpoint->info.multicast_client.groupname)); // connect socket NPT_CHECK(sender.Connect(NPT_SocketAddress(address, endpoint->info.multicast_client.port))); // get the streams if (input_stream) { NPT_CHECK(sender.GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(sender.GetOutputStream(*output_stream)); } return NPT_SUCCESS; } break; case ENDPOINT_TYPE_UDP_SERVER: { NPT_UdpSocket listener; // info if (Options.verbose) { NPT_Debug("listening on port %d", endpoint->info.udp_server.port); } // listen on port, any addr NPT_CHECK(listener.Bind(NPT_SocketAddress(NPT_IpAddress::Any, endpoint->info.udp_server.port))); // get the streams if (input_stream) { NPT_CHECK(listener.GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(listener.GetOutputStream(*output_stream)); } return NPT_SUCCESS; } break; case ENDPOINT_TYPE_TCP_SERVER: { NPT_TcpServerSocket server; NPT_Socket* client; // info if (Options.verbose) { NPT_Debug("waiting for client on port %d\n", endpoint->info.tcp_server.port); } // bind to the address NPT_CHECK(server.Bind(NPT_SocketAddress(NPT_IpAddress::Any, endpoint->info.tcp_server.port))); // wait for connection NPT_CHECK(server.WaitForNewClient(client)); // info if (Options.verbose) { NPT_Debug("client connected\n"); } // get the streams if (input_stream) { NPT_CHECK(client->GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(client->GetOutputStream(*output_stream)); } delete client; return NPT_SUCCESS; } break; case ENDPOINT_TYPE_MULTICAST_SERVER: { NPT_UdpMulticastSocket listener; // info if (Options.verbose) { NPT_Debug("listening on port %d\n", endpoint->info.multicast_server.port); } // listen on port, any addr NPT_CHECK(listener.Bind(NPT_SocketAddress(NPT_IpAddress::Any, endpoint->info.multicast_server.port))); // info if (Options.verbose) { NPT_Debug("joining multicast group %s\n", endpoint->info.multicast_server.groupname); } // resolve name NPT_IpAddress address; NPT_CHECK(address.ResolveName(endpoint->info.multicast_server.groupname)); // join the group NPT_CHECK(listener.JoinGroup(address)); // get the streams if (input_stream) { NPT_CHECK(listener.GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(listener.GetOutputStream(*output_stream)); } return NPT_SUCCESS; } break; case ENDPOINT_TYPE_FILE: { // create a file object NPT_File file(endpoint->info.file.name); if (endpoint->direction == ENDPOINT_DIRECTION_IN) { NPT_CHECK(file.Open(NPT_FILE_OPEN_MODE_READ | NPT_FILE_OPEN_MODE_UNBUFFERED)); } else { NPT_CHECK(file.Open(NPT_FILE_OPEN_MODE_WRITE | NPT_FILE_OPEN_MODE_CREATE| NPT_FILE_OPEN_MODE_UNBUFFERED)); } // get the streams if (input_stream) { NPT_CHECK(file.GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(file.GetOutputStream(*output_stream)); } return NPT_SUCCESS; } break; case ENDPOINT_TYPE_SERIAL_PORT: { // create a serial port object NPT_SerialPort serial_port(endpoint->info.serial_port.name); NPT_CHECK(serial_port.Open(endpoint->info.serial_port.speed)); // get the streams if (input_stream) { NPT_CHECK(serial_port.GetInputStream(*input_stream)); } if (output_stream) { NPT_CHECK(serial_port.GetOutputStream(*output_stream)); } return NPT_SUCCESS; } break; } 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; }