/*---------------------------------------------------------------------- | NPT_NetworkNameResolver::Resolve +---------------------------------------------------------------------*/ NPT_Result NPT_NetworkNameResolver::Resolve(const char* name, NPT_List<NPT_IpAddress>& addresses, NPT_Timeout /*timeout*/) { // empty the list first addresses.Clear(); // get the addr list //struct addrinfo hints; //NPT_SetMemory(&hints, 0, sizeof(hints)); //hints.ai_family = PF_UNSPEC; //hints.ai_socktype = SOCK_STREAM; //hints.ai_flags = AI_DEFAULT; struct addrinfo *infos = NULL; int result = getaddrinfo(name, /* hostname */ NULL, /* servname */ NULL, /* hints */ &infos /* res */); if (result != 0) { return MapGetAddrInfoErrorCode(result); } for (struct addrinfo* info = infos; info && addresses.GetItemCount() < NPT_BSD_NETWORK_MAX_ADDR_LIST_LENGTH; info = info->ai_next) { unsigned int expected_length; if (info->ai_family == AF_INET) { expected_length = sizeof(struct sockaddr_in); #if defined(NPT_CONFIG_ENABLE_IPV6) } else if (info->ai_family == AF_INET6) { expected_length = sizeof(struct sockaddr_in6); #endif } else { continue; } if ((unsigned int)info->ai_addrlen < expected_length) continue; if (info->ai_protocol != 0 && info->ai_protocol != IPPROTO_TCP) continue; if (info->ai_family == AF_INET) { struct sockaddr_in* inet_addr = (struct sockaddr_in*)info->ai_addr; NPT_IpAddress address(ntohl(inet_addr->sin_addr.s_addr)); addresses.Add(address); } #if defined(NPT_CONFIG_ENABLE_IPV6) else if (info->ai_family == AF_INET6) { struct sockaddr_in6* inet_addr = (struct sockaddr_in6*)info->ai_addr; NPT_IpAddress address(NPT_IpAddress::IPV6, inet_addr->sin6_addr.s6_addr, 16, inet_addr->sin6_scope_id); addresses.Add(address); } #endif } freeaddrinfo(infos); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_PSPQueue::Push +---------------------------------------------------------------------*/ NPT_Result NPT_PSPQueue::Push(NPT_QueueItem* item) { // lock the mutex that protects the list m_Items.Lock(); // check that we have not exceeded the max //if (m_MaxItems) { // while (m_Items.GetItemCount() >= m_MaxItems) { // // wait until some items have been removed // //NPT_Debug(":: NPT_PSPQueue::Push - waiting for queue to empty\n"); // pthread_cond_wait(&m_CanPushOrPopCondition, &m_Mutex); // } //} // add the item to the list m_Items.Add(item); // if the list was previously empty, signal the condition // to wake up the waiting thread //if (m_Items.GetItemCount() == 1) { // pthread_cond_signal(&m_CanPushOrPopCondition); //} // unlock the mutex m_Items.Unlock(); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_File::GetRoots +---------------------------------------------------------------------*/ NPT_Result NPT_File::GetRoots(NPT_List<NPT_String>& roots) { roots.Clear(); roots.Add("/"); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_PosixQueue::Push +---------------------------------------------------------------------*/ NPT_Result NPT_PosixQueue::Push(NPT_QueueItem* item, NPT_Timeout timeout) { struct timespec timed; struct timeval now; // get current time from system if (gettimeofday(&now, NULL)) { return NPT_FAILURE; } now.tv_usec += timeout * 1000; if (now.tv_usec >= 1000000) { now.tv_sec += now.tv_usec / 1000000; now.tv_usec = now.tv_usec % 1000000; } // setup timeout timed.tv_sec = now.tv_sec; timed.tv_nsec = now.tv_usec * 1000; // lock the mutex that protects the list if (pthread_mutex_lock(&m_Mutex)) { return NPT_FAILURE; } NPT_Result result = NPT_SUCCESS; // check that we have not exceeded the max if (m_MaxItems) { while (m_Items.GetItemCount() >= m_MaxItems) { // wait until some items have been removed //NPT_Debug(":: NPT_PosixQueue::Push - waiting for queue to empty\n"); if (timeout == NPT_TIMEOUT_INFINITE) { pthread_cond_wait(&m_CanPushOrPopCondition, &m_Mutex); } else { int wait_res = pthread_cond_timedwait(&m_CanPushOrPopCondition, &m_Mutex, &timed); if (wait_res == ETIMEDOUT) { result = NPT_ERROR_TIMEOUT; break; } } } } // add the item to the list if (result == NPT_SUCCESS) { m_Items.Add(item); // if the list was previously empty, signal the condition // to wake up the waiting thread if (m_Items.GetItemCount() == 1) { pthread_cond_signal(&m_CanPushOrPopCondition); } } // unlock the mutex pthread_mutex_unlock(&m_Mutex); return result; }
NPT_List<const Object*> Container::getChildren() const { NPT_List<const Object*> ls; for (NPT_Ordinal i = 0; i < childCount(); i++) { ls.Add(childAt(i)); } return ls; }
/*---------------------------------------------------------------------- | NPT_File::ListDir +---------------------------------------------------------------------*/ NPT_Result NPT_File::ListDir(const char* path, NPT_List<NPT_String>& entries, NPT_Ordinal start /* = 0 */, NPT_Cardinal max /* = 0 */) { // default return value entries.Clear(); // check the arguments if (path == NULL) return NPT_ERROR_INVALID_PARAMETERS; // list the entries DIR *directory = opendir(path); if (directory == NULL) return NPT_ERROR_NO_SUCH_ITEM; NPT_Cardinal count = 0; for (;;) { struct dirent* entry_pointer = NULL; #if defined(NPT_CONFIG_HAVE_READDIR_R) struct dirent entry; int result = readdir_r(directory, &entry, &entry_pointer); if (result != 0 || entry_pointer == NULL) break; #else entry_pointer = readdir(directory); if (entry_pointer == NULL) break; #endif // ignore odd names if (entry_pointer->d_name[0] == '\0') continue; // ignore . and .. if (entry_pointer->d_name[0] == '.' && entry_pointer->d_name[1] == '\0') { continue; } if (entry_pointer->d_name[0] == '.' && entry_pointer->d_name[1] == '.' && entry_pointer->d_name[2] == '\0') { continue; } // continue if we still have some items to skip if (start > 0) { --start; continue; } entries.Add(NPT_String(entry_pointer->d_name)); // stop when we have reached the maximum requested if (max && ++count == max) break; } closedir(directory); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_PosixQueue::Push +---------------------------------------------------------------------*/ NPT_Result NPT_PosixQueue::Push(NPT_QueueItem* item, NPT_Timeout timeout) { struct timespec timed; if (timeout != NPT_TIMEOUT_INFINITE) { NPT_CHECK(GetTimeOut(timeout, timed)); } // lock the mutex that protects the list if (pthread_mutex_lock(&m_Mutex)) { return NPT_FAILURE; } NPT_Result result = NPT_SUCCESS; // check that we have not exceeded the max if (m_MaxItems) { while (m_Items.GetItemCount() >= m_MaxItems) { // wait until we can push ++m_PushersWaitingCount; if (timeout == NPT_TIMEOUT_INFINITE) { pthread_cond_wait(&m_CanPushCondition, &m_Mutex); --m_PushersWaitingCount; } else { int wait_res = pthread_cond_timedwait(&m_CanPushCondition, &m_Mutex, &timed); --m_PushersWaitingCount; if (wait_res == ETIMEDOUT) { result = NPT_ERROR_TIMEOUT; break; } } if (m_Aborting) { result = NPT_ERROR_INTERRUPTED; break; } } } // add the item to the list if (result == NPT_SUCCESS) { m_Items.Add(item); // wake up any thread that may be waiting to pop if (m_PoppersWaitingCount) { pthread_cond_broadcast(&m_CanPopCondition); } } // unlock the mutex pthread_mutex_unlock(&m_Mutex); return result; }
/*---------------------------------------------------------------------- | NPT_NetworkInterface::GetNetworkInterfaces +---------------------------------------------------------------------*/ NPT_Result NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces) { union SceNetApctlInfo info; int ret = sceNetApctlGetInfo(SCE_NET_APCTL_INFO_IP_ADDRESS, &info); if (ret < 0) { return NPT_FAILURE; } NPT_IpAddress primary_address; if (NPT_FAILED(primary_address.Parse(info.ip_address))) { return NPT_FAILURE; } NPT_IpAddress netmask; if (NPT_FAILED(netmask.Parse(info.netmask))) { return NPT_FAILURE; } NPT_IpAddress broadcast_address; NPT_Flags flags = 0; flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST; flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST; // get mac address SceNetEtherAddr mac_info; ret = sceNetGetLocalEtherAddr(&mac_info); if (ret < 0) { return NPT_FAILURE; } NPT_MacAddress mac(TYPE_IEEE_802_11, mac_info.data, SCE_NET_ETHER_ADDR_LEN); // create an interface object char iface_name[5]; iface_name[0] = 'i'; iface_name[1] = 'f'; iface_name[2] = '0'; iface_name[3] = '0'; iface_name[4] = '\0'; NPT_NetworkInterface* iface = new NPT_NetworkInterface(iface_name, mac, flags); // set the interface address NPT_NetworkInterfaceAddress iface_address( primary_address, broadcast_address, NPT_IpAddress::Any, netmask); iface->AddAddress(iface_address); // add the interface to the list interfaces.Add(iface); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_String::Split +---------------------------------------------------------------------*/ NPT_List<NPT_String> NPT_String::Split(const char* separator) const { NPT_List<NPT_String> result; NPT_Size separator_length = NPT_StringLength(separator); // sepcial case for empty separators if (separator_length == 0) { result.Add(*this); return result; } int current = 0; int next; do { next = Find(separator, current); unsigned int end = (next>=0?(unsigned int)next:GetLength()); result.Add(SubString(current, end-current)); current = next+separator_length; } while (next >= 0); return result; }
/*---------------------------------------------------------------------- | NPT_File::ListDir +---------------------------------------------------------------------*/ NPT_Result NPT_File::ListDir(const char* path, NPT_List<NPT_String>& entries, NPT_Ordinal start /* = 0 */, NPT_Cardinal max /* = 0 */) { NPT_WIN32_USE_CHAR_CONVERSION; // default return value entries.Clear(); // check the arguments if (path == NULL || path[0] == '\0') return NPT_ERROR_INVALID_PARAMETERS; // construct a path name with a \* wildcard at the end NPT_String path_pattern = path; if (path_pattern.EndsWith("\\") || path_pattern.EndsWith("/")) { path_pattern += "*"; } else { path_pattern += "\\*"; } // list the entries WIN32_FIND_DATAW find_data; HANDLE find_handle = FindFirstFileW(NPT_WIN32_A2W(path_pattern.GetChars()), &find_data); if (find_handle == INVALID_HANDLE_VALUE) return MapError(GetLastError()); NPT_Cardinal count = 0; do { if (NPT_File_ProcessFindData(&find_data)) { // continue if we still have entries to skip if (start > 0) { --start; continue; } entries.Add(NPT_WIN32_W2A(find_data.cFileName)); // stop when we have reached the maximum requested if (max && ++count == max) return NPT_SUCCESS; } } while (FindNextFileW(find_handle, &find_data)); DWORD last_error = GetLastError(); FindClose(find_handle); if (last_error != ERROR_NO_MORE_FILES) return MapError(last_error); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_File::GetRoots +---------------------------------------------------------------------*/ NPT_Result NPT_File::GetRoots(NPT_List<NPT_String>& roots) { roots.Clear(); #if defined(_WIN32_WCE) || defined(_XBOX) return NPT_ERROR_NOT_IMPLEMENTED; #else DWORD drives = GetLogicalDrives(); for (unsigned int i=0; i<26; i++) { if (drives & (1<<i)) { char drive_name[4] = {'A'+i, ':', '\\', 0}; roots.Add(drive_name); } } return NPT_SUCCESS; #endif }
/*---------------------------------------------------------------------- | NPT_Win32Queue::Push +---------------------------------------------------------------------*/ NPT_Result NPT_Win32Queue::Push(NPT_QueueItem* item, NPT_Timeout timeout) { // lock the mutex that protects the list NPT_CHECK(m_Mutex.Lock()); // check that we have not exceeded the max if (m_MaxItems) { while (m_Items.GetItemCount() >= m_MaxItems) { // we must wait until some items have been removed // reset the condition to indicate that the queue is full m_CanPushCondition->Reset(); // unlock the mutex so that another thread can pop m_Mutex.Unlock(); // wait for the condition to signal that we can push NPT_Result result = m_CanPushCondition->Wait(timeout); if (NPT_FAILED(result)) return result; // relock the mutex so that we can check the list again NPT_CHECK(m_Mutex.Lock()); } } // add the item to the list m_Items.Add(item); // wake up the threads waiting to pop m_CanPopCondition->Signal(); // unlock the mutex m_Mutex.Unlock(); return NPT_SUCCESS; }
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); }
/*---------------------------------------------------------------------- | NPT_NetworkInterface::GetNetworkInterfaces +---------------------------------------------------------------------*/ NPT_Result NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces) { int net = socket(AF_INET, SOCK_DGRAM, 0); // Try to get the config until we have enough memory for it // According to "Unix Network Programming", some implementations // do not return an error when the supplied buffer is too small // so we need to try, increasing the buffer size every time, // until we get the same size twice. We cannot assume success when // the returned size is smaller than the supplied buffer, because // some implementations can return less that the buffer size if // another structure does not fit. unsigned int buffer_size = 4096; // initial guess unsigned int last_size = 0; struct ifconf config; unsigned char* buffer; for (; buffer_size < 65536;) { buffer = new unsigned char[buffer_size]; config.ifc_len = buffer_size; config.ifc_buf = (char*)buffer; if (ioctl(net, SIOCGIFCONF, &config) < 0) { if (errno != EINVAL || last_size != 0) { return NPT_ERROR_BASE_UNIX-errno; } } else { if ((unsigned int)config.ifc_len == last_size) { // same size, we can use the buffer break; } // different size, we need to reallocate last_size = config.ifc_len; } // supply 4096 more bytes more next time around buffer_size += 4096; delete[] buffer; } // iterate over all objects unsigned char *entries; for (entries = buffer; entries < buffer+config.ifc_len;) { struct ifreq* entry = (struct ifreq*)entries; // get the size of the addresses unsigned int address_length; #if defined(NPT_CONFIG_HAVE_SOCKADDR_SA_LEN) address_length = sizeof(struct sockaddr) > entry->ifr_addr.sa_len ? sizeof(sockaddr) : entry->ifr_addr.sa_len; #else switch (entry->ifr_addr.sa_family) { #if defined(AF_INET6) case AF_INET6: address_length = sizeof(struct sockaddr_in6); break; #endif // defined(AF_INET6) default: address_length = sizeof(struct sockaddr); break; } #endif // point to the next entry entries += address_length + sizeof(entry->ifr_name); // ignore anything except AF_INET and AF_LINK addresses if (entry->ifr_addr.sa_family != AF_INET #if defined(AF_LINK) && entry->ifr_addr.sa_family != AF_LINK #endif ) { continue; } // get detailed info about the interface NPT_Flags flags = 0; #if defined(SIOCGIFFLAGS) struct ifreq query = *entry; if (ioctl(net, SIOCGIFFLAGS, &query) < 0) continue; // process the flags if ((query.ifr_flags & IFF_UP) == 0) { // the interface is not up, ignore it continue; } if (query.ifr_flags & IFF_BROADCAST) { flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST; } if (query.ifr_flags & IFF_LOOPBACK) { flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK; } #if defined(IFF_POINTOPOINT) if (query.ifr_flags & IFF_POINTOPOINT) { flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT; } #endif // defined(IFF_POINTOPOINT) if (query.ifr_flags & IFF_PROMISC) { flags |= NPT_NETWORK_INTERFACE_FLAG_PROMISCUOUS; } if (query.ifr_flags & IFF_MULTICAST) { flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST; } #endif // defined(SIOCGIFFLAGS) // get a pointer to an interface we've looped over before // or create a new one NPT_NetworkInterface* interface = NULL; for (NPT_List<NPT_NetworkInterface*>::Iterator iface_iter = interfaces.GetFirstItem(); iface_iter; ++iface_iter) { if ((*iface_iter)->GetName() == (const char*)entry->ifr_name) { interface = *iface_iter; break; } } if (interface == NULL) { // create a new interface object interface = new NPT_NetworkInterface(entry->ifr_name, flags); // add the interface to the list interfaces.Add(interface); // get the mac address #if defined(SIOCGIFHWADDR) if (ioctl(net, SIOCGIFHWADDR, &query) == 0) { NPT_MacAddress::Type mac_addr_type; unsigned int mac_addr_length = IFHWADDRLEN; switch (query.ifr_addr.sa_family) { #if defined(ARPHRD_ETHER) case ARPHRD_ETHER: mac_addr_type = NPT_MacAddress::TYPE_ETHERNET; break; #endif #if defined(ARPHRD_LOOPBACK) case ARPHRD_LOOPBACK: mac_addr_type = NPT_MacAddress::TYPE_LOOPBACK; length = 0; break; #endif #if defined(ARPHRD_PPP) case ARPHRD_PPP: mac_addr_type = NPT_MacAddress::TYPE_PPP; mac_addr_length = 0; break; #endif #if defined(ARPHRD_IEEE80211) case ARPHRD_IEEE80211: mac_addr_type = NPT_MacAddress::TYPE_IEEE_802_11; break; #endif default: mac_addr_type = NPT_MacAddress::TYPE_UNKNOWN; mac_addr_length = sizeof(query.ifr_addr.sa_data); break; } interface->SetMacAddress(mac_addr_type, (const unsigned char*)query.ifr_addr.sa_data, mac_addr_length); } #endif } switch (entry->ifr_addr.sa_family) { case AF_INET: { // primary address NPT_IpAddress primary_address(ntohl(((struct sockaddr_in*)&entry->ifr_addr)->sin_addr.s_addr)); // broadcast address NPT_IpAddress broadcast_address; #if defined(SIOCGIFBRDADDR) if (flags & NPT_NETWORK_INTERFACE_FLAG_BROADCAST) { if (ioctl(net, SIOCGIFBRDADDR, &query) == 0) { broadcast_address.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr)); } } #endif // point to point address NPT_IpAddress destination_address; #if defined(SIOCGIFDSTADDR) if (flags & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT) { if (ioctl(net, SIOCGIFDSTADDR, &query) == 0) { destination_address.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr)); } } #endif // netmask NPT_IpAddress netmask(0xFFFFFFFF); #if defined(SIOCGIFNETMASK) if (ioctl(net, SIOCGIFNETMASK, &query) == 0) { netmask.Set(ntohl(((struct sockaddr_in*)&query.ifr_addr)->sin_addr.s_addr)); } #endif // add the address to the interface NPT_NetworkInterfaceAddress iface_address( primary_address, broadcast_address, destination_address, netmask); interface->AddAddress(iface_address); break; } #if defined(AF_LINK) && defined(NPT_CONFIG_HAVE_SOCKADDR_DL) case AF_LINK: { struct sockaddr_dl* mac_addr = (struct sockaddr_dl*)&entry->ifr_addr; NPT_MacAddress::Type mac_addr_type = NPT_MacAddress::TYPE_UNKNOWN; switch (mac_addr->sdl_type) { #if defined(IFT_LOOP) case IFT_LOOP: mac_addr_type = NPT_MacAddress::TYPE_LOOPBACK; break; #endif #if defined(IFT_ETHER) case IFT_ETHER: mac_addr_type = NPT_MacAddress::TYPE_ETHERNET; break; #endif #if defined(IFT_PPP) case IFT_PPP: mac_addr_type = NPT_MacAddress::TYPE_PPP; break; #endif } interface->SetMacAddress(mac_addr_type, (const unsigned char*)(&mac_addr->sdl_data[mac_addr->sdl_nlen]), mac_addr->sdl_alen); break; } #endif } } // free resources delete[] buffer; close(net); return NPT_SUCCESS; }
/*---------------------------------------------------------------------- | NPT_NetworkInterface::GetNetworkInterfaces +---------------------------------------------------------------------*/ NPT_Result NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces) { int result = 0; struct ifaddrs * ifaddrsList = NULL; struct ifaddrs * ifaddr = NULL; NPT_Flags flags = 0; result = getifaddrs(&ifaddrsList); if( result != 0 || ifaddrsList == NULL) return NPT_FAILURE; for(ifaddr = ifaddrsList; NULL!= ifaddr; ifaddr = ifaddr->ifa_next) { if(ifaddr->ifa_addr == NULL /*|| ifaddr->ifa_addr->sa_family == AF_INET6*/) continue; // process the flags if ((ifaddr->ifa_flags & IFF_UP) == 0) { // the interface is not up, ignore it continue; } if (ifaddr->ifa_flags & IFF_BROADCAST) { flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST; } if (ifaddr->ifa_flags & IFF_LOOPBACK) { flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK; } #if defined(IFF_POINTOPOINT) if (ifaddr->ifa_flags & IFF_POINTOPOINT) { flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT; } #endif // defined(IFF_POINTOPOINT) if (ifaddr->ifa_flags & IFF_PROMISC) { flags |= NPT_NETWORK_INTERFACE_FLAG_PROMISCUOUS; } if (ifaddr->ifa_flags & IFF_MULTICAST) { flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST; } NPT_NetworkInterface* interface = NULL; for (NPT_List<NPT_NetworkInterface*>::Iterator iface_iter = interfaces.GetFirstItem(); iface_iter; ++iface_iter) { if ((*iface_iter)->GetName() == (const char*)ifaddr->ifa_name) { interface = *iface_iter; break; } } // create a new interface object if(interface == NULL) interface = new NPT_NetworkInterface(ifaddr->ifa_name, flags); if (interface == NULL) continue; // get the mac address NPT_MacAddress::Type mac_addr_type; unsigned int mac_addr_length = IFHWADDRLEN; switch (ifaddr->ifa_addr->sa_family) { case AF_LOCAL: case AF_INET: #if defined(AF_LINK) case AF_LINK: #endif mac_addr_type = NPT_MacAddress::TYPE_ETHERNET; #if defined(ARPHRD_LOOPBACK) mac_addr_type = NPT_MacAddress::TYPE_LOOPBACK; length = 0; #endif break; #if defined(AF_PPP) case AF_PPP: mac_addr_type = NPT_MacAddress::TYPE_PPP; mac_addr_length = 0; break; #endif #if defined(AF_IEEE80211) case AF_IEEE80211: mac_addr_type = NPT_MacAddress::TYPE_IEEE_802_11; break; #endif default: mac_addr_type = NPT_MacAddress::TYPE_UNKNOWN; mac_addr_length = sizeof(ifaddr->ifa_addr->sa_data); break; } if(interface->GetMacAddress().GetLength() == 0) interface->SetMacAddress(mac_addr_type, (const unsigned char*)ifaddr->ifa_addr->sa_data, mac_addr_length); #if defined(NPT_CONFIG_HAVE_NET_IF_DL_H) if (ifaddr->ifa_addr->sa_family == AF_LINK) { //Refer to LLADDR struct sockaddr_dl * socket_dl = (struct sockaddr_dl *)ifaddr->ifa_addr; interface->SetMacAddress(mac_addr_type, (const unsigned char*)socket_dl->sdl_data+socket_dl->sdl_nlen, socket_dl->sdl_alen); } #endif switch (ifaddr->ifa_addr->sa_family) { case AF_INET: { // primary address NPT_IpAddress primary_address( ntohl(((struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr)); // broadcast address NPT_IpAddress broadcast_address; if ((flags & NPT_NETWORK_INTERFACE_FLAG_BROADCAST) && ifaddr->ifa_dstaddr) { broadcast_address.Set(ntohl(((struct sockaddr_in*)ifaddr->ifa_dstaddr)->sin_addr.s_addr)); } // point to point address NPT_IpAddress destination_address; if ((flags & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT) && ifaddr->ifa_dstaddr) { destination_address.Set(ntohl(((struct sockaddr_in*)ifaddr->ifa_dstaddr)->sin_addr.s_addr)); } // netmask NPT_IpAddress netmask(0xFFFFFFFF); if(ifaddr->ifa_netmask) netmask.Set(ntohl(((struct sockaddr_in*)ifaddr->ifa_netmask)->sin_addr.s_addr)); // add the address to the interface NPT_NetworkInterfaceAddress iface_address(primary_address, broadcast_address, destination_address, netmask); interface->AddAddress(iface_address); break; } } // add the interface to the list interfaces.Add(interface); } freeifaddrs(ifaddrsList); return NPT_SUCCESS; }
void CUPnP::RegisterUserdata(void* ptr) { NPT_AutoLock lock(g_UserDataLock); g_UserData.Add(ptr); }
/*---------------------------------------------------------------------- | NPT_NetworkInterface::GetNetworkInterfaces +---------------------------------------------------------------------*/ NPT_Result NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces) { // create a socket to talk to the TCP/IP stack SOCKET net; if((net = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0)) == INVALID_SOCKET) { return NPT_FAILURE; } // get a list of interfaces INTERFACE_INFO query[32]; // get up to 32 interfaces DWORD bytes_returned; int io_result = WSAIoctl(net, SIO_GET_INTERFACE_LIST, NULL, 0, &query, sizeof(query), &bytes_returned, NULL, NULL); if (io_result == SOCKET_ERROR) { closesocket(net); return NPT_FAILURE; } // we don't need the socket anymore closesocket(net); // Display interface information int interface_count = (bytes_returned/sizeof(INTERFACE_INFO)); unsigned int iface_index = 0; for (int i=0; i<interface_count; i++) { SOCKADDR_IN* address; NPT_Flags flags = 0; // primary address address = (SOCKADDR_IN*)&query[i].iiAddress; NPT_IpAddress primary_address(ntohl(address->sin_addr.s_addr)); // netmask address = (SOCKADDR_IN*)&query[i].iiNetmask; NPT_IpAddress netmask(ntohl(address->sin_addr.s_addr)); // broadcast address address = (SOCKADDR_IN*)&query[i].iiBroadcastAddress; NPT_IpAddress broadcast_address(ntohl(address->sin_addr.s_addr)); { // broadcast address is incorrect unsigned char addr[4]; for(int i=0; i<4; i++) { addr[i] = (primary_address.AsBytes()[i] & netmask.AsBytes()[i]) | ~netmask.AsBytes()[i]; } broadcast_address.Set(addr); } // ignore interfaces that are not up if (!(query[i].iiFlags & IFF_UP)) { continue; } if (query[i].iiFlags & IFF_BROADCAST) { flags |= NPT_NETWORK_INTERFACE_FLAG_BROADCAST; } if (query[i].iiFlags & IFF_MULTICAST) { flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST; } if (query[i].iiFlags & IFF_LOOPBACK) { flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK; } if (query[i].iiFlags & IFF_POINTTOPOINT) { flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT; } // mac address (no support for this for now) NPT_MacAddress mac; // create an interface object char iface_name[5]; iface_name[0] = 'i'; iface_name[1] = 'f'; iface_name[2] = '0'+(iface_index/10); iface_name[3] = '0'+(iface_index%10); iface_name[4] = '\0'; NPT_NetworkInterface* iface = new NPT_NetworkInterface(iface_name, mac, flags); // set the interface address NPT_NetworkInterfaceAddress iface_address( primary_address, broadcast_address, NPT_IpAddress::Any, netmask); iface->AddAddress(iface_address); // add the interface to the list interfaces.Add(iface); // increment the index (used for generating the name iface_index++; } 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>()); }
/*---------------------------------------------------------------------- | NPT_NetworkInterface::GetNetworkInterfaces +---------------------------------------------------------------------*/ NPT_Result NPT_NetworkInterface::GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& interfaces) { IP_ADAPTER_ADDRESSES* iface_list = NULL; ULONG size = sizeof(IP_ADAPTER_INFO); // get the interface table for(;;) { iface_list = (IP_ADAPTER_ADDRESSES*)malloc(size); DWORD result = GetAdaptersAddresses(AF_INET, 0, NULL, iface_list, &size); if (result == NO_ERROR) { break; } else { // free and try again free(iface_list); if (result != ERROR_BUFFER_OVERFLOW) { return NPT_FAILURE; } } } // iterate over the interfaces for (IP_ADAPTER_ADDRESSES* iface = iface_list; iface; iface = iface->Next) { // skip this interface if it is not up if (iface->OperStatus != IfOperStatusUp) continue; // get the interface type and mac address NPT_MacAddress::Type mac_type; switch (iface->IfType) { case IF_TYPE_ETHERNET_CSMACD: mac_type = NPT_MacAddress::TYPE_ETHERNET; break; case IF_TYPE_SOFTWARE_LOOPBACK: mac_type = NPT_MacAddress::TYPE_LOOPBACK; break; case IF_TYPE_PPP: mac_type = NPT_MacAddress::TYPE_PPP; break; default: mac_type = NPT_MacAddress::TYPE_UNKNOWN; break; } NPT_MacAddress mac(mac_type, iface->PhysicalAddress, iface->PhysicalAddressLength); // compute interface flags NPT_Flags flags = 0; if (!(iface->Flags & IP_ADAPTER_NO_MULTICAST)) flags |= NPT_NETWORK_INTERFACE_FLAG_MULTICAST; if (iface->IfType == IF_TYPE_SOFTWARE_LOOPBACK) flags |= NPT_NETWORK_INTERFACE_FLAG_LOOPBACK; if (iface->IfType == IF_TYPE_PPP) flags |= NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT; // compute the unicast address (only the first one is supported for now) NPT_IpAddress primary_address; if (iface->FirstUnicastAddress) { if (iface->FirstUnicastAddress->Address.lpSockaddr == NULL) continue; if (iface->FirstUnicastAddress->Address.iSockaddrLength != sizeof(SOCKADDR_IN)) continue; SOCKADDR_IN* address = (SOCKADDR_IN*)iface->FirstUnicastAddress->Address.lpSockaddr; if (address->sin_family != AF_INET) continue; primary_address.Set(ntohl(address->sin_addr.s_addr)); } NPT_IpAddress broadcast_address; // not supported yet NPT_IpAddress netmask; // not supported yet // convert the interface name to UTF-8 // BUG in Wine: FriendlyName is NULL unsigned int iface_name_length = (unsigned int)iface->FriendlyName?wcslen(iface->FriendlyName):0; char* iface_name = new char[4*iface_name_length+1]; int result = WideCharToMultiByte( CP_UTF8, 0, iface->FriendlyName, iface_name_length, iface_name, 4*iface_name_length+1, NULL, NULL); if (result > 0) { iface_name[result] = '\0'; } else { iface_name[0] = '\0'; } // create an interface descriptor NPT_NetworkInterface* iface_object = new NPT_NetworkInterface(iface_name, mac, flags); NPT_NetworkInterfaceAddress iface_address( primary_address, broadcast_address, NPT_IpAddress::Any, netmask); iface_object->AddAddress(iface_address); // cleanup delete[] iface_name; // add the interface to the list interfaces.Add(iface_object); } free(iface_list); return NPT_SUCCESS; }