/*---------------------------------------------------------------------- | PLT_SsdpAnnounceInterfaceIterator class +---------------------------------------------------------------------*/ NPT_Result PLT_SsdpAnnounceInterfaceIterator::operator()(NPT_NetworkInterface*& net_if) const { // don't use this interface address if it's not broadcast capable if (m_Broadcast && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_BROADCAST)) { return NPT_FAILURE; } NPT_List<NPT_NetworkInterfaceAddress>::Iterator niaddr = net_if->GetAddresses().GetFirstItem(); if (!niaddr) return NPT_FAILURE; // Remove disconnected interfaces NPT_IpAddress addr = (*niaddr).GetPrimaryAddress(); if (!addr.ToString().Compare("0.0.0.0")) return NPT_FAILURE; if (!m_Broadcast && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) && !(net_if->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK)) { NPT_LOG_INFO_2("Not a valid interface: %s (flags: %d)", (const char*)addr.ToString(), net_if->GetFlags()); return NPT_FAILURE; } NPT_HttpUrl url; NPT_UdpMulticastSocket multicast_socket; NPT_UdpSocket broadcast_socket; NPT_UdpSocket* socket; if (m_Broadcast) { url = NPT_HttpUrl((*niaddr).GetBroadcastAddress().ToString(), 1900, "*"); socket = &broadcast_socket; } else { url = NPT_HttpUrl("239.255.255.250", 1900, "*"); NPT_CHECK_SEVERE(multicast_socket.SetInterface(addr)); socket = &multicast_socket; multicast_socket.SetTimeToLive(PLT_Constants::GetInstance().GetAnnounceMulticastTimeToLive()); } NPT_HttpRequest req(url, "NOTIFY", NPT_HTTP_PROTOCOL_1_1); PLT_HttpHelper::SetHost(req, "239.255.255.250:1900"); // Location header valid only for ssdp:alive or ssdp:update messages if (m_Type != PLT_ANNOUNCETYPE_BYEBYE) { PLT_UPnPMessageHelper::SetLocation(req, m_Device->GetDescriptionUrl(addr.ToString())); } NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_Type)); #if defined(PLATINUM_UPNP_SPECS_STRICT) // delay alive only as we don't want to delay when stopping if (m_Type != PLT_ANNOUNCETYPE_BYEBYE) { NPT_System::Sleep(NPT_TimeInterval(PLT_DLNA_SSDP_DELAY_GROUP)); } NPT_CHECK_SEVERE(m_Device->Announce(req, *socket, m_Type)); #endif return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | PLT_HttpServer::Start +---------------------------------------------------------------------*/ NPT_Result PLT_HttpServer::Start() { NPT_Result res = NPT_FAILURE; // we can't restart an aborted server if (m_Aborted) return NPT_ERROR_INVALID_STATE; // if we're given a port for our http server, try it if (m_Port) { res = SetListenPort(m_Port, m_ReuseAddress); // return right away if failed and not allowed to try again randomly if (NPT_FAILED(res) && !m_AllowRandomPortOnBindFailure) { NPT_CHECK_SEVERE(res); } } // try random port now if (!m_Port || NPT_FAILED(res)) { int retries = 100; do { int random = NPT_System::GetRandomInteger(); int port = (unsigned short)(1024 + (random % 1024)); if (NPT_SUCCEEDED(SetListenPort(port, m_ReuseAddress))) { break; } } while (--retries > 0); if (retries == 0) NPT_CHECK_SEVERE(NPT_FAILURE); } // keep track of port server has successfully bound m_Port = m_BoundPort; // Tell server to try to listen to more incoming sockets // (this could fail silently) if (m_TaskManager->GetMaxTasks() > 20) { m_Socket.Listen(m_TaskManager->GetMaxTasks()); } // start a task to listen for incoming connections // and keep it around so we can abort the server m_HttpListenTask = new PLT_HttpListenTask(this, &m_Socket, false); m_TaskManager->StartTask(m_HttpListenTask, NULL, false); NPT_SocketInfo info; m_Socket.GetInfo(info); NPT_LOG_INFO_2("HttpServer listening on %s:%d", (const char*)info.local_address.GetIpAddress().ToString(), m_Port); return NPT_SUCCESS; }
NPT_Result TaskGroup::wait(NPT_Timeout timeout) { NPT_Result nr; { WriteLocker locker(m_stateLock); if (m_state != State_Stopping) { return NPT_ERROR_INVALID_STATE; } } if (timeout == NPT_TIMEOUT_INFINITE) { /*for (NPT_Ordinal i = 0; i < m_threadList.GetItemCount(); i++) { TaskThread *thread = *m_threadList.GetItem(i); thread->Wait(); delete thread; } m_threadList.Clear();*/ NPT_LOG_INFO_2("TaskGroup %p waiting for %d threads", this, m_threadList.GetItemCount()); while (m_threadList.GetItemCount() > 0) { NPT_Cardinal count = m_threadList.GetItemCount(); for (NPT_Ordinal i = 0; i < count; ) { NPT_List<TaskThread*>::Iterator it = m_threadList.GetItem(i); TaskThread *thread = *it; NPT_LOG_INFO_2("TaskGroup %p waiting for thread %p", this, thread); if (NPT_SUCCEEDED(thread->Wait(3000))) { NPT_LOG_INFO_2("TaskGroup %p waited thread %p, fine!", this, thread); delete thread; m_threadList.Erase(it); count--; } else { NPT_LOG_INFO_2("TaskGroup %p thread %p still pending, continue", this, thread); i++; } } } } else { NPT_Timeout waitTick = 10; if (waitTick > timeout) { waitTick = timeout; } NPT_TimeStamp ts1, ts2; NPT_Timeout totalTick = 0; while (m_threadList.GetItemCount() != 0 && timeout >= totalTick) { NPT_Cardinal count = m_threadList.GetItemCount(); NPT_Ordinal i = 0; while (i < count) { NPT_List<TaskThread*>::Iterator it = m_threadList.GetItem(i); TaskThread *thread = *it; NPT_System::GetCurrentTimeStamp(ts1); nr = thread->Wait(waitTick); NPT_System::GetCurrentTimeStamp(ts2); totalTick += (ts2 - ts1).ToMillis(); if (NPT_SUCCEEDED(nr)) { m_threadList.Erase(it); delete thread; --count; } else { i++; } if (timeout >= totalTick) { NPT_Timeout remainTick = timeout - totalTick; if (waitTick > remainTick) { waitTick = remainTick; } } else { waitTick = 0; } } } } if (m_threadList.GetItemCount() == 0) { m_state = State_Stopped; } return m_threadList.GetItemCount() == 0 ? NPT_SUCCESS : NPT_ERROR_TIMEOUT; }