void DviSessionUpnp::ParseRequestUri(const Brx& aUrlTail, DviDevice** aDevice, DviService** aService) { Parser parser(iReaderRequest->Uri()); Brn tmp = parser.Next('/'); if (tmp.Bytes() > 0) { Error(HttpStatus::kPreconditionFailed); } Brn udn = parser.Next('/'); DviDevice* device = DviDeviceMap::Find(udn); *aDevice = device; if (device == NULL) { Error(HttpStatus::kPreconditionFailed); } Brn serviceName = parser.Next('/'); if (parser.Remaining() != aUrlTail) { Error(HttpStatus::kPreconditionFailed); } const TUint count = device->ServiceCount(); for (TUint i=0; i<count; i++) { DviService& service = device->Service(i); if (service.ServiceType().PathUpnp() == serviceName) { *aService = &service; break; } } }
void DviSessionUpnp::Subscribe() { LOG(kDvEvent, "Subscription request from "); iHeaderCallback.Log(); LOG(kDvEvent, "\n"); if (iHeaderSid.Received()) { Renew(); return; } if (!iHeaderCallback.Received() || !iHeaderNt.Received() || !iHeaderTimeout.Received()) { Error(HttpStatus::kPreconditionFailed); } DviDevice* device; DviService* service; ParseRequestUri(DviProtocolUpnp::kEventUrlTail, &device, &service); if (device == NULL || service == NULL) { Error(HttpStatus::kPreconditionFailed); } TUint duration = iHeaderTimeout.Timeout(); Brh sid; device->CreateSid(sid); SubscriptionDataUpnp* data = new SubscriptionDataUpnp(iHeaderCallback.Endpoint(), iHeaderCallback.Uri()); DviSubscription* subscription = new DviSubscription(*device, *iPropertyWriterFactory, data, sid, duration); iPropertyWriterFactory->SubscriptionAdded(*subscription); DviSubscriptionManager::AddSubscription(*subscription); if (iHeaderExpect.Continue()) { iWriterResponse->WriteStatus(HttpStatus::kContinue, Http::eHttp11); iWriterResponse->WriteFlush(); } // respond to subscription request iResponseStarted = true; iWriterResponse->WriteStatus(HttpStatus::kOk, Http::eHttp11); WriteServerHeader(*iWriterResponse); IWriterAscii& writerSid = iWriterResponse->WriteHeaderField(HeaderSid::kHeaderSid); writerSid.Write(HeaderSid::kFieldSidPrefix); writerSid.Write(subscription->Sid()); writerSid.WriteFlush(); IWriterAscii& writerTimeout = iWriterResponse->WriteHeaderField(HeaderTimeout::kHeaderTimeout); writerTimeout.Write(HeaderTimeout::kFieldTimeoutPrefix); writerTimeout.WriteUint(duration); writerTimeout.WriteFlush(); iWriterResponse->WriteHeader(Http::kHeaderConnection, Http::kConnectionClose); iWriterResponse->WriteFlush(); iResponseEnded = true; LOG(kDvEvent, "Subscription complete for "); iHeaderCallback.Log(); LOG(kDvEvent, ", sid is "); LOG(kDvEvent, subscription->Sid()); LOG(kDvEvent, "\n"); // Start subscription, prompting delivery of the first update (covering all state variables) service->AddSubscription(subscription); }
DviProtocolUpnpAdapterSpecificData* DviProtocolUpnp::AddInterface(const NetworkAdapter& aAdapter) { TIpAddress addr = aAdapter.Address(); Bws<Uri::kMaxUriBytes> uriBase; TUint port = iServer->Port(addr); DviDevice* root = (iDevice.IsRoot()? &iDevice : iDevice.Root()); root->GetUriBase(uriBase, addr, port, *this); DviProtocolUpnpAdapterSpecificData* adapter = new DviProtocolUpnpAdapterSpecificData(iDvStack, *this, aAdapter, uriBase, port); iAdapters.push_back(adapter); return adapter; }
void SuiteAlive::Test() { Environment& env = iDvStack.Env(); Blocker* blocker = new Blocker(env); CpListenerBasic* listener = new CpListenerBasic; NetworkAdapter* nif = env.NetworkAdapterList().CurrentAdapter(kAdapterCookie); SsdpListenerMulticast* listenerMulticast = new SsdpListenerMulticast(env, nif->Address()); nif->RemoveRef(kAdapterCookie); TInt listenerId = listenerMulticast->AddNotifyHandler(listener); listenerMulticast->Start(); DviDevice* device = new DviDeviceStandard(iDvStack, gNameDevice1); device->SetAttribute("Upnp.Domain", "a.b.c"); device->SetAttribute("Upnp.Type", "type1"); device->SetAttribute("Upnp.Version", "1"); AddService(device, new DviService(iDvStack, "a.b.c", "service1", 1)); AddService(device, new DviService(iDvStack, "a.b.c", "service2", 1)); device->SetEnabled(); blocker->Wait(1); /* we expect 5 messages but linux sometimes reports multicast messages from all subnets to listeners on any single subnet so just check that we've received a multiple of 5 messages */ TEST(listener->TotalAlives() > 0); TEST(listener->TotalAlives() == listener->TotalByeByes()); TEST(listener->TotalAlives() % 5 == 0); TUint byebyes = listener->TotalByeByes(); Functor disabled = MakeFunctor(*this, &SuiteAlive::Disabled); device->SetDisabled(disabled); iSem.Wait(); blocker->Wait(1); /* semaphore being signalled implies that the device has been disabled. We may require some extra time to receive the multicast byebye confirming this */ TEST(listener->TotalByeByes() > byebyes); TEST(listener->TotalByeByes() % 5 == 0); TUint alives = listener->TotalAlives(); byebyes = listener->TotalByeByes(); device->SetEnabled(); blocker->Wait(1); TEST(listener->TotalAlives() > alives); TEST(listener->TotalAlives() - alives == listener->TotalByeByes() - byebyes); TEST(listener->TotalAlives() % 5 == 0); // Control point doesn't process ssdp:update notifications // check that updates are basically working by counting the extra alive messages instead alives = listener->TotalAlives(); device->SetAttribute("Upnp.TestUpdate", "1"); blocker->Wait(1); TEST(listener->TotalAlives() > alives); TEST(listener->TotalAlives() % 5 == 0); device->Destroy(); listenerMulticast->RemoveNotifyHandler(listenerId); delete listenerMulticast; delete listener; delete blocker; }
DvProvider::DvProvider(DviDevice& aDevice, const TChar* aDomain, const TChar* aType, TUint aVersion) : iDelayPropertyUpdates(false) , iPropertyChanged(false) { iService = new DviService(aDomain, aType, aVersion); aDevice.AddService(iService); // ownership of service passed to aDevice }
void DviDeviceMap::Add(DviDevice& aDevice) { DviDeviceMap& self = DviStack::DeviceMap(); self.iLock.Wait(); Brn udn(aDevice.Udn()); self.iMap.insert(std::pair<Brn,DviDevice*>(udn, &aDevice)); self.iLock.Signal(); }
void DviDeviceMap::WriteResource(const Brx& aUriTail, TIpAddress aInterface, std::vector<char*>& aLanguageList, IResourceWriter& aResourceWriter) { iLock.Wait(); Parser parser(aUriTail); (void)parser.Next('/'); // skip leading slash Brn dir = parser.Next('/'); if (dir.Bytes() > 0) { Map::iterator it = iMap.find(dir); if (it != iMap.end()) { DviDevice* device = it->second; iLock.Signal(); device->WriteResource(parser.Remaining(), aInterface, aLanguageList, aResourceWriter); return; } } iLock.Signal(); }
void DviProtocolUpnp::Enable() { iLock.Wait(); // check we have at least the basic attributes requried for advertisement ASSERT(Domain().Bytes() > 0); ASSERT(Type().Bytes() > 0); ASSERT(Version() > 0); for (TUint i=0; i<iAdapters.size(); i++) { DviProtocolUpnpAdapterSpecificData* adapter = iAdapters[i]; Bws<Uri::kMaxUriBytes> uriBase; DviDevice* root = (iDevice.IsRoot()? &iDevice : iDevice.Root()); adapter->UpdateServerPort(*iServer); root->GetUriBase(uriBase, adapter->Interface(), adapter->ServerPort(), *this); adapter->UpdateUriBase(uriBase); adapter->ClearDeviceXml(); if (iDevice.ResourceManager() != NULL) { const TChar* name = 0; GetAttribute("FriendlyName", &name); adapter->BonjourRegister(name, iDevice.Udn(), kProtocolName, iDevice.kResourceDir); /*GetAttribute("MdnsHostName", &name); if (name != NULL) { iDvStack.MdnsProvider()->MdnsSetHostName(name); Bwh redirectedPath(iDevice.Udn().Bytes() + kProtocolName.Bytes() + iDevice.kResourceDir.Bytes() + 4); redirectedPath.Append('/'); Uri::Escape(redirectedPath, iDevice.Udn()); redirectedPath.Append('/'); redirectedPath.Append(kProtocolName); redirectedPath.Append('/'); redirectedPath.Append(iDevice.kResourceDir); redirectedPath.Append('/'); iDvStack.ServerUpnp().Redirect(Brn("/"), redirectedPath); }*/ } } for (TUint i=0; i<iAdapters.size(); i++) { iAdapters[i]->SendByeByeThenAlive(*this); } iLock.Signal(); QueueAliveTimer(); }
void DviDeviceMap::Remove(DviDevice& aDevice) { DviDeviceMap& self = DviStack::DeviceMap(); self.iLock.Wait(); Brn udn(aDevice.Udn()); Map::iterator it = self.iMap.find(udn); if (it != self.iMap.end()) { self.iMap.erase(it); } self.iLock.Signal(); }
void DviProviderSubscriptionLongPoll::Subscribe(IDvInvocation& aInvocation, const Brx& aClientId, const Brx& aUdn, const Brx& aService, TUint aRequestedDuration, IDvInvocationResponseString& aSid, IDvInvocationResponseUint& aDuration) { if (aRequestedDuration > kTimeoutLongPollSecs) { aRequestedDuration = kTimeoutLongPollSecs; } DviDevice* device = iDvStack.DeviceMap().Find(aUdn); if (device == NULL) { aInvocation.Error(kErrorCodeBadDevice, kErrorDescBadDevice); } DviService* service = NULL; const TUint serviceCount = device->ServiceCount(); for (TUint i=0; i<serviceCount; i++) { DviService* s = &device->Service(i); if (s->ServiceType().PathUpnp() == aService) { service = s; break; } } if (service == NULL) { aInvocation.Error(kErrorCodeBadService, kErrorDescBadService); } Brh sid; device->CreateSid(sid); TUint timeout = aRequestedDuration; DviSubscription* subscription = new DviSubscription(iDvStack, *device, iPropertyUpdateCollection, NULL, sid, timeout); aInvocation.StartResponse(); aSid.Write(subscription->Sid()); aSid.WriteFlush(); aDuration.Write(timeout); aInvocation.EndResponse(); // Start subscription, prompting availability of the first update (covering all state variables) iPropertyUpdateCollection.AddSubscription(aClientId, subscription); iDvStack.SubscriptionManager().AddSubscription(*subscription); service->AddSubscription(subscription); }
DviProtocolUpnp::DviProtocolUpnp(DviDevice& aDevice) : iDevice(aDevice) , iDvStack(aDevice.GetDvStack()) , iLock("DMUP") , iUpdateCount(0) , iSuppressScheduledEvents(false) { SetAttribute(kAttributeKeyVersionMajor, "1"); SetAttribute(kAttributeKeyVersionMinor, "1"); iLock.Wait(); iServer = &(iDvStack.ServerUpnp()); NetworkAdapterList& adapterList = iDvStack.Env().NetworkAdapterList(); Functor functor = MakeFunctor(*this, &DviProtocolUpnp::HandleInterfaceChange); iCurrentAdapterChangeListenerId = adapterList.AddCurrentChangeListener(functor); iSubnetListChangeListenerId = adapterList.AddSubnetListChangeListener(functor); std::vector<NetworkAdapter*>* subnetList = adapterList.CreateSubnetList(); AutoNetworkAdapterRef ref(iDvStack.Env(), "DviProtocolUpnp ctor"); const NetworkAdapter* current = ref.Adapter(); if (current != NULL) { AddInterface(*current); } else { for (TUint i=0; i<subnetList->size(); i++) { NetworkAdapter* subnet = (*subnetList)[i]; try { AddInterface(*subnet); } catch (NetworkError& ) { // some hosts may have adapters that don't support multicast // we can't differentiate between no support ever and transient failure // (typical on Windows & Mac after hibernation) so just ignore this exception // and trust that we'll get advertised on another interface. char* adapterName = subnet->FullName(); LOG2(kTrace, kError, "DvDevice unable to use adapter %s\n", adapterName); delete adapterName; } } } NetworkAdapterList::DestroySubnetList(subnetList); iAliveTimer = new Timer(iDvStack.Env(), MakeFunctor(*this, &DviProtocolUpnp::SendAliveNotifications), "DviProtocolUpnp"); iLock.Signal(); }
DviProviderSubscriptionLongPoll::DviProviderSubscriptionLongPoll(DviDevice& aDevice) : DvProviderOpenhomeOrgSubscriptionLongPoll1(aDevice) , iDvStack(aDevice.GetDvStack()) , iPropertyUpdateCollection(iDvStack.PropertyUpdateCollection()) , iLock("LPMX") , iShutdown("LPSH", 0) , iExit(false) , iClientCount(0) { EnableActionSubscribe(); EnableActionUnsubscribe(); EnableActionRenew(); EnableActionGetPropertyUpdates(); iShutdown.Signal(); iMaxClientCount = iDvStack.Env().InitParams()->DvNumServerThreads() / 2; ASSERT(iMaxClientCount > 0); UpdateReadySignal empty; for (TUint i=0; i<iMaxClientCount; i++) { iUpdateReady.push_back(empty); } }
void SuiteMsearch::Test() { DviDevice* device = new DviDeviceStandard(iDvStack, gNameDevice1); iDevices[0] = device; device->SetAttribute("Upnp.Domain", "upnp.org"); device->SetAttribute("Upnp.Type", "test1"); device->SetAttribute("Upnp.Version", "1"); AddService(device, new DviService(iDvStack, "upnp.org", "service1", 1)); AddService(device, new DviService(iDvStack, "openhome.org", "service2", 3)); AddService(device, new DviService(iDvStack, "upnp.org", "service3", 1)); DviService* service = new DviService(iDvStack, "upnp.org", "service1", 1); TEST_THROWS(device->AddService(service), AssertionFailed); service->RemoveRef(); device->SetEnabled(); service = new DviService(iDvStack, "upnp.org", "service4", 1); TEST_THROWS(device->AddService(service), AssertionFailed); service->RemoveRef(); device = new DviDeviceStandard(iDvStack, gNameDevice2); iDevices[1] = device; device->SetAttribute("Upnp.Domain", "openhome.org"); device->SetAttribute("Upnp.Type", "test2"); device->SetAttribute("Upnp.Version", "2"); AddService(device, new DviService(iDvStack, "openhome.org", "service4", 2)); AddService(device, new DviService(iDvStack, "openhome.org", "service5", 1)); device = new DviDeviceStandard(iDvStack, gNameDevice2Embedded1); iDevices[1]->AddDevice(device); device->SetAttribute("Upnp.Domain", "openhome.org"); device->SetAttribute("Upnp.Type", "test3"); device->SetAttribute("Upnp.Version", "1"); AddService(device, new DviService(iDvStack, "upnp.org", "service1", 1)); AddService(device, new DviService(iDvStack, "openhome.org", "service6", 1)); AddService(device, new DviService(iDvStack, "openhome.org", "service2", 3)); service = new DviService(iDvStack, "openhome.org", "service5", 1); TEST_THROWS(device->AddService(service), AssertionFailed); service->RemoveRef(); iDevices[1]->SetEnabled(); device->SetEnabled(); device = new DviDeviceStandard(iDvStack, kNameDummy); TEST_THROWS(iDevices[1]->AddDevice(device), AssertionFailed); device->Destroy(); //Wait(); // allow time for initial annoucements to be delivered TestMsearchAll(); TestMsearchRoot(); TestMsearchUuid(); TestMsearchDeviceType(); TestMsearchServiceType(); }
TBool DviSessionLpec::SubscriptionData::Matches(DviDevice& aDevice, DviService& aService) const { return (iDevice->Udn() == aDevice.Udn() && iService->ServiceType().FullName() == aService.ServiceType().FullName()); }
void mdvi_shrink_glyph_grey(DviContext *dvi, DviFont *font, DviFontChar *pk, DviGlyph *dest) { int rows_left, rows; int cols_left, cols, init_cols; long sampleval, samplemax; BmUnit *old_ptr; void *image; int w, h; int x, y; DviGlyph *glyph; BITMAP *map; Ulong *pixels; int npixels; Ulong colortab[2]; int hs, vs; DviDevice *dev; hs = dvi->params.hshrink; vs = dvi->params.vshrink; dev = &dvi->device; glyph = &pk->glyph; map = (BITMAP *)glyph->data; x = (int)glyph->x / hs; init_cols = (int)glyph->x - x * hs; if(init_cols <= 0) init_cols += hs; else x++; w = x + ROUND((int)glyph->w - glyph->x, hs); cols = (int)glyph->y + 1; y = cols / vs; rows = cols - y * vs; if(rows <= 0) { rows += vs; y--; } h = y + ROUND((int)glyph->h - cols, vs) + 1; ASSERT(w && h); /* before touching anything, do this */ image = dev->create_image(dev->device_data, w, h, BITMAP_BITS); if(image == NULL) { mdvi_shrink_glyph(dvi, font, pk, dest); return; } /* save these colors */ pk->fg = MDVI_CURRFG(dvi); pk->bg = MDVI_CURRBG(dvi); samplemax = vs * hs; npixels = samplemax + 1; pixels = get_color_table(&dvi->device, npixels, pk->fg, pk->bg, dvi->params.gamma, dvi->params.density); if(pixels == NULL) { npixels = 2; colortab[0] = pk->fg; colortab[1] = pk->bg; pixels = &colortab[0]; } /* setup the new glyph */ dest->data = image; dest->x = x; dest->y = glyph->y / vs; dest->w = w; dest->h = h; y = 0; old_ptr = map->data; rows_left = glyph->h; while(rows_left && y < h) { x = 0; if(rows > rows_left) rows = rows_left; cols_left = glyph->w; cols = init_cols; while(cols_left && x < w) { if(cols > cols_left) cols = cols_left; sampleval = do_sample(old_ptr, map->stride, glyph->w - cols_left, cols, rows); /* scale the sample value by the number of grey levels */ if(npixels - 1 != samplemax) sampleval = ((npixels-1) * sampleval) / samplemax; ASSERT(sampleval < npixels); dev->put_pixel(image, x, y, pixels[sampleval]); cols_left -= cols; cols = hs; x++; } for(; x < w; x++) dev->put_pixel(image, x, y, pixels[0]); old_ptr = bm_offset(old_ptr, rows * map->stride); rows_left -= rows; rows = vs; y++; } for(; y < h; y++) { for(x = 0; x < w; x++) dev->put_pixel(image, x, y, pixels[0]); } dev->image_done(image); DEBUG((DBG_BITMAPS, "shrink_glyph_grey: (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n", glyph->w, glyph->h, glyph->x, glyph->y, dest->w, dest->h, dest->x, dest->y)); }