/*---------------------------------------------------------------------- | PLT_SsdpSender::SendSsdp +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpSender::SendSsdp(NPT_HttpResponse& response, const char* usn, const char* target, NPT_UdpSocket& socket, bool notify, const NPT_SocketAddress* addr /* = NULL */) { NPT_CHECK_SEVERE(FormatPacket(response, usn, target, socket, notify)); // logging NPT_LOG_FINE("Sending SSDP:"); PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINE, &response); // use a memory stream to write all the data NPT_MemoryStream stream; NPT_Result res = response.Emit(stream); if (NPT_FAILED(res)) return res; // copy stream into a data packet and send it NPT_LargeSize size; stream.GetSize(size); if (size != (NPT_Size)size) return NPT_ERROR_OUT_OF_RANGE; NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size); return socket.Send(packet, addr); }
/*---------------------------------------------------------------------- | PLT_SsdpSender::SendSsdp +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpSender::SendSsdp(NPT_HttpRequest& request, const char* usn, const char* target, NPT_UdpSocket& socket, bool notify, const NPT_SocketAddress* addr /* = NULL */) { NPT_CHECK_SEVERE(FormatPacket(request, usn, target, socket, notify)); // logging NPT_String prefix = NPT_String::Format("Sending SSDP %s packet for %s", (const char*)request.GetMethod(), usn); PLT_LOG_HTTP_MESSAGE(NPT_LOG_LEVEL_FINER, prefix, &request); // use a memory stream to write all the data NPT_MemoryStream stream; NPT_Result res = request.Emit(stream); NPT_CHECK(res); // copy stream into a data packet and send it NPT_LargeSize size; stream.GetSize(size); if (size != (NPT_Size)size) NPT_CHECK(NPT_ERROR_OUT_OF_RANGE); NPT_DataBuffer packet(stream.GetData(), (NPT_Size)size); NPT_CHECK_WARNING(socket.Send(packet, 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; }
/*---------------------------------------------------------------------- | NPT_LogUdpHandler::Log +---------------------------------------------------------------------*/ void NPT_LogUdpHandler::Log(const NPT_LogRecord& record) { // format the record NPT_String msg; NPT_LogTcpHandler::FormatRecord(record, msg); // send it in a datagram NPT_DataBuffer buffer(msg.GetChars(), msg.GetLength()+1, false); m_Socket.Send(buffer, &m_Target); }
/*---------------------------------------------------------------------- | 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; }