/*---------------------------------------------------------------------- | GetEndPointUdpSocket +---------------------------------------------------------------------*/ static NPT_Result GetEndPointUdpSocket(EndPoint* endpoint, NPT_UdpSocket*& udp_socket) { // default return values udp_socket = NULL; switch (endpoint->type) { case ENDPOINT_TYPE_UDP_SERVER: { udp_socket = new NPT_UdpSocket(); // info if (Options.verbose) { NPT_Debug("listening on port %d", endpoint->info.udp_server.port); } // listen on port, any addr return udp_socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, endpoint->info.udp_server.port)); } break; case ENDPOINT_TYPE_MULTICAST_SERVER: { NPT_UdpMulticastSocket* udp_multicast_socket = new NPT_UdpMulticastSocket(); udp_socket = udp_multicast_socket; // info if (Options.verbose) { NPT_Debug("listening on port %d\n", endpoint->info.multicast_server.port); } // listen on port, any addr NPT_CHECK(udp_socket->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(udp_multicast_socket->JoinGroup(address)); return NPT_SUCCESS; } break; default: return NPT_FAILURE; } return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_UPnP::Start() +---------------------------------------------------------------------*/ NPT_Result PLT_UPnP::Start() { NPT_LOG_INFO("Starting UPnP..."); NPT_AutoLock lock(m_Lock); if (m_Started == true) NPT_CHECK_SEVERE(NPT_ERROR_INVALID_STATE); NPT_List<NPT_IpAddress> ips; PLT_UPnPMessageHelper::GetIPAddresses(ips); /* Create multicast socket and bind on 1900. If other apps didn't play nicely by setting the REUSE_ADDR flag, this could fail */ NPT_UdpMulticastSocket* socket = new NPT_UdpMulticastSocket(); NPT_CHECK_SEVERE(socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900), true)); /* Join multicast group for every ip we found */ NPT_CHECK_SEVERE(ips.ApplyUntil(PLT_SsdpInitMulticastIterator(socket), NPT_UntilResultNotEquals(NPT_SUCCESS))); /* create the ssdp listener */ m_SsdpListenTask = new PLT_SsdpListenTask(socket); NPT_CHECK_SEVERE(m_TaskManager.StartTask(m_SsdpListenTask)); /* start devices & ctrlpoints */ // TODO: Starting devices and ctrlpoints could fail? m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStartIterator(m_SsdpListenTask)); m_Devices.Apply(PLT_UPnP_DeviceStartIterator(m_SsdpListenTask)); m_Started = true; return NPT_SUCCESS; }
NPT_Result Start() { NPT_Result result = NPT_FAILURE; // bind // randomly try a port for our http server int retries = 100; do { int random = NPT_System::GetRandomInteger(); NPT_IpPort port = (unsigned short)(50000 + (random % 15000)); result = m_Socket.Bind( NPT_SocketAddress(NPT_IpAddress::Any, m_Port?m_Port:port), false); if (NPT_SUCCEEDED(result) || m_Port) break; } while (--retries > 0); if (NPT_FAILED(result) || retries == 0) return NPT_FAILURE; // remember that we're bound NPT_SocketInfo info; m_Socket.GetInfo(info); m_Port = info.local_address.GetPort(); return NPT_Thread::Start(); }
/*---------------------------------------------------------------------- | UdpServerLoop +---------------------------------------------------------------------*/ static void UdpServerLoop(int port) { NPT_UdpSocket listener; // info if (Options.verbose) { NPT_Debug("listening on port %d\n", port); } NPT_Result result = listener.Bind(NPT_SocketAddress(NPT_IpAddress::Any, port)); if (NPT_FAILED(result)) { NPT_Debug("ERROR: Bind() failed (%d)\n", result); } // packet loop NPT_DataBuffer packet(32768); NPT_SocketAddress address; do { result = listener.Receive(packet, &address); if (NPT_SUCCEEDED(result)) { if (Options.verbose) { NPT_String ip = address.GetIpAddress().ToString(); NPT_Debug("Received %d bytes from %s:%d\n", packet.GetDataSize(), ip.GetChars(), address.GetPort()); } listener.Send(packet, &address); } } while (NPT_SUCCEEDED(result)); }
/*---------------------------------------------------------------------- | NPT_LogTcpHandler::Connect +---------------------------------------------------------------------*/ NPT_Result NPT_LogTcpHandler::Connect() { /* create a socket */ NPT_TcpClientSocket tcp_socket; /* connect to the host */ NPT_IpAddress ip_address; NPT_CHECK(ip_address.ResolveName(m_Host)); NPT_Result result = tcp_socket.Connect(NPT_SocketAddress(ip_address, m_Port), NPT_LOG_TCP_HANDLER_DEFAULT_CONNECT_TIMEOUT); if (NPT_FAILED(result)) { return result; } /* get the stream */ return tcp_socket.GetOutputStream(m_Stream); }
NPT_Result SsdpConnector::start() { if (m_started) { return NPT_ERROR_INVALID_STATE; } m_socket = new NPT_UdpMulticastSocket(NPT_SOCKET_FLAG_CANCELLABLE); m_socket->SetInterface(m_ifAddr); NPT_Result nr; nr = m_socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, 1900), true); if (NPT_FAILED(nr)) { delete m_socket; m_socket = NULL; return nr; } NPT_IpAddress groupAddr(239, 255, 255, 250); nr = m_socket->JoinGroup(groupAddr, m_ifAddr); if (NPT_FAILED(nr)) { delete m_socket; m_socket = NULL; return nr; } NPT_SocketInfo socketInfo; m_socket->GetInfo(socketInfo); m_port = socketInfo.local_address.GetPort(); m_abortFlag = false; nr = NPT_Thread::Start(); if (NPT_FAILED(nr)) { delete m_socket; m_socket = NULL; return nr; } m_started = true; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_UPnP::Start() +---------------------------------------------------------------------*/ NPT_Result PLT_UPnP::Start() { NPT_LOG_INFO("Starting UPnP..."); NPT_AutoLock lock(m_Lock); if (m_Started == true) return NPT_FAILURE; NPT_Socket* socket = m_Multicast?new NPT_UdpMulticastSocket(): new NPT_UdpSocket(); NPT_CHECK_SEVERE(socket->Bind(NPT_SocketAddress(NPT_IpAddress::Any, m_Port))); /* create the ssdp listener */ m_SsdpListenTask = new PLT_SsdpListenTask(socket, m_Multicast, true); NPT_CHECK_SEVERE(m_TaskManager.StartTask(m_SsdpListenTask)); /* start devices & ctrlpoints */ m_CtrlPoints.Apply(PLT_UPnP_CtrlPointStartIterator(m_SsdpListenTask)); m_Devices.Apply(PLT_UPnP_DeviceStartIterator(m_SsdpListenTask)); m_Started = true; return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | TcpServerLoop +---------------------------------------------------------------------*/ static void TcpServerLoop(int port) { NPT_TcpServerSocket listener; NPT_Result result = listener.Bind(NPT_SocketAddress(NPT_IpAddress::Any, port)); if (NPT_FAILED(result)) { NPT_Debug("ERROR: Bind() failed (%d)\n", result); } NPT_Socket* client; for (;;) { NPT_Debug("waiting for client on port %d\n", port); NPT_Result result = listener.WaitForNewClient(client); NPT_SocketInfo socket_info; client->GetInfo(socket_info); NPT_Debug("client connected from %s:%d\n", socket_info.remote_address.GetIpAddress().ToString().GetChars(), socket_info.remote_address.GetPort()); NPT_InputStreamReference input; client->GetInputStream(input); NPT_OutputStreamReference output; client->GetOutputStream(output); do { char buffer[1024]; NPT_Size bytes_read; result = input->Read(buffer, sizeof(buffer), &bytes_read); if (NPT_SUCCEEDED(result)) { NPT_Debug("read %ld bytes\n", bytes_read); output->Write(buffer, bytes_read); } } while (NPT_SUCCEEDED(result)); delete client; } }
/*---------------------------------------------------------------------- | 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; }
void FrontEnd::broadcastLocked(DeviceImplInfo *deviceInfo, bool avail) { NPT_TimeStamp ts; NPT_System::GetCurrentTimeStamp(ts); NPT_List<MatchContext*> matchList; if (deviceInfo) { deviceInfo->m_updateTS = ts; MatchContext *matchContext = new MatchContext(); if (deviceInfo->m_deviceImpl->match("ssdp:all", matchContext->matches)) { matchList.Add(matchContext); matchContext->deviceUuid = deviceInfo->m_deviceImpl->uuid(); matchContext->expireSeconds = deviceInfo->m_deviceImpl->m_expireSeconds; matchContext->descPath = deviceInfo->m_deviceImpl->m_descPath; matchContext->httpRoot = deviceInfo->m_context.m_httpRoot; } else { delete matchContext; } } else { for (NPT_Ordinal i = 0; i < m_deviceImplList.GetItemCount(); i++) { NPT_List<DeviceImplInfo*>::Iterator it = m_deviceImplList.GetItem(i); DeviceImplInfo *info = *it; info->m_updateTS = ts; MatchContext *matchContext = new MatchContext(); if (info->m_deviceImpl->match("ssdp:all", matchContext->matches)) { matchList.Add(matchContext); matchContext->deviceUuid = info->m_deviceImpl->uuid(); matchContext->expireSeconds = info->m_deviceImpl->m_expireSeconds; matchContext->descPath = info->m_deviceImpl->m_descPath; matchContext->httpRoot = info->m_context.m_httpRoot; } else { delete matchContext; } } } NPT_SocketAddress targetAddr(NPT_IpAddress(239, 255, 255, 250), 1900); for (NPT_Ordinal i = 0; i < m_ifList.GetItemCount(); i++) { Interface *nif = *m_ifList.GetItem(i); NPT_UdpSocket sock(NPT_SOCKET_FLAG_CANCELLABLE); sock.Bind(NPT_SocketAddress(nif->m_context.m_ifAddr, 0)); for (NPT_Ordinal j = 0; j < matchList.GetItemCount(); j++) { MatchContext *matchContext = *matchList.GetItem(j); NPT_String location = NPT_String::Format("http://%s:%d%s%s", nif->m_context.m_ifAddr.ToString().GetChars(), nif->m_context.m_httpPort, matchContext->httpRoot.GetChars(), matchContext->descPath.GetChars()); for (NPT_Ordinal k = 0; k < matchContext->matches.GetItemCount(); k++) { NPT_List<DeviceImplMatch>::Iterator it2 = matchContext->matches.GetItem(k); NPT_String msg; if (avail) { //msg = NPT_String::Format("NOTIFY * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nCACHE-CONTROL: max-age=%d\r\nLOCATION: %s\r\nNT: %s\r\nNTS: ssdp:alive\r\nSERVER: %s\r\nUSN: %s\r\n\r\n", // matchContext->expireSeconds, location.GetChars(), it2->m_st.GetChars(), m_serverHeader.GetChars(), it2->m_usn.GetChars()); msg = NPT_String::Format("NOTIFY * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nCACHE-CONTROL: max-age=%d\r\nLOCATION: %s\r\nNT: %s\r\nNTS: ssdp:alive\r\nSERVER: %s\r\nUSN: %s\r\nCUSTOM:%s\r\n\r\n", matchContext->expireSeconds, location.GetChars(), it2->m_st.GetChars(), m_serverHeader.GetChars(), it2->m_usn.GetChars(), m_DevName.GetChars()); } else { msg = NPT_String::Format("NOTIFY * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nNT: %s\r\nNTS: ssdp:byebye\r\nUSN: %s\r\nCUSTOM:%s\r\n\r\n", it2->m_st.GetChars(), it2->m_usn.GetChars(), m_DevName.GetChars()); } NPT_DataBuffer packet(msg.GetChars(), msg.GetLength(), false); sock.Send(packet, &targetAddr); } } } matchList.Apply(NPT_ObjectDeleter<MatchContext>()); }
void FrontEnd::processSsdpSearch(SsdpServerTask *task, Interface *intf, const NPT_DataBuffer& data, const NPT_SocketAddress& fromAddr) { do { NPT_HttpRequest *req; NPT_InputStreamReference inputStream0(new NPT_MemoryStream(data.GetData(), data.GetDataSize())); NPT_BufferedInputStream inputStream(inputStream0); if (NPT_FAILED(NPT_HttpRequest::Parse(inputStream, NULL, req))) { break; } PtrHolder<NPT_HttpRequest> req1(req); if (req->GetMethod().Compare("M-SEARCH") != 0 || req->GetProtocol().Compare(NPT_HTTP_PROTOCOL_1_1) != 0 || req->GetUrl().GetPath().Compare("*") != 0) { break; } NPT_HttpHeader *hdrMan = req->GetHeaders().GetHeader("MAN"); if (!hdrMan || hdrMan->GetValue().Compare("\"ssdp:discover\"") != 0) { break; } NPT_HttpHeader *hdrHost = req->GetHeaders().GetHeader("HOST"); if (!hdrHost || (hdrHost->GetValue().Compare("239.255.255.250:1900") != 0 && hdrHost->GetValue().Compare("239.255.255.250") != 0)) { break; } int mx; NPT_HttpHeader *hdrMX = req->GetHeaders().GetHeader("MX"); if (!hdrMX || NPT_FAILED(NPT_ParseInteger(hdrMX->GetValue(), mx)) || mx < 1) { break; } if (mx > 120) { mx = 120; } NPT_HttpHeader *hdrST = req->GetHeaders().GetHeader("ST"); if (!hdrST) { break; } NPT_List<MatchContext*> matchList; NPT_UdpSocket sock(NPT_SOCKET_FLAG_CANCELLABLE); sock.Bind(NPT_SocketAddress(intf->m_context.m_ifAddr, 0)); NPT_SharedVariable waitVar; waitVar.SetValue(0); { ReadLocker locker(m_dsLock); for (NPT_Ordinal i = 0; i < m_deviceImplList.GetItemCount(); i++) { NPT_List<DeviceImplInfo*>::Iterator it = m_deviceImplList.GetItem(i); DeviceImplInfo *info = *it; MatchContext *matchContext = new MatchContext(); if (info->m_deviceImpl->match(hdrST->GetValue(), matchContext->matches)) { matchList.Add(matchContext); matchContext->deviceUuid = info->m_deviceImpl->uuid(); matchContext->expireSeconds = info->m_deviceImpl->m_expireSeconds; matchContext->descPath = info->m_deviceImpl->m_descPath; matchContext->httpRoot = info->m_context.m_httpRoot; } else { delete matchContext; } } } SsdpSearchAbortCallback abortCallback(&sock, &waitVar); if (task->registerAbortCallback(&abortCallback)) { for (NPT_Ordinal i = 0; i < matchList.GetItemCount(); i++) { MatchContext *matchContext = *matchList.GetItem(i); NPT_String location = NPT_String::Format("http://%s:%d%s%s", intf->m_context.m_ifAddr.ToString().GetChars(), intf->m_context.m_httpPort, matchContext->httpRoot.GetChars(), matchContext->descPath.GetChars()); bool broken = false; for (NPT_Ordinal j = 0; j < matchContext->matches.GetItemCount(); j++) { NPT_List<DeviceImplMatch>::Iterator it2 = matchContext->matches.GetItem(j); NPT_Timeout timeout = NPT_System::GetRandomInteger() % (mx * 1000); // TODO: wait or not ??? timeout = 0; if (NPT_SUCCEEDED(waitVar.WaitWhileEquals(0, timeout))) { break; } { ReadLocker locker(m_dsLock); if (m_deviceImplIndex.HasKey(matchContext->deviceUuid)) { NPT_TimeStamp ts; NPT_System::GetCurrentTimeStamp(ts); NPT_String dateStr = NPT_DateTime(ts).ToString(NPT_DateTime::FORMAT_RFC_1123); NPT_String resp = NPT_String::Format("HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=%d\r\nDATE: %s\r\nEXT: \r\nLOCATION: %s\r\nSERVER: %s\r\nST: %s\r\nUSN: %s\r\nCUSTOM:%s\r\n\r\n", matchContext->expireSeconds, dateStr.GetChars(), location.GetChars(), m_serverHeader.GetChars(), it2->m_st.GetChars(), it2->m_usn.GetChars(), m_DevName.GetChars()); NPT_DataBuffer packet(resp.GetChars(), resp.GetLength(), false); sock.Send(packet, &fromAddr); } } } if (broken) { break; } } task->unregisterAbortCallback(&abortCallback); } matchList.Apply(NPT_ObjectDeleter<MatchContext>()); } while (false); }