void DviProtocolUpnpServiceXmlWriter::WriteServiceXml(WriterBwh& aWriter, const DviService& aService, const DviProtocolUpnp& aDevice) { aWriter.Write("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); aWriter.Write("<scpd xmlns=\"urn:schemas-upnp-org:service-1-0\">"); writeSpecVersion(aWriter, aDevice); aWriter.Write("<actionList>"); const std::vector<DvAction>& actions = aService.DvActions(); for (TUint i=0; i<actions.size(); i++) { const Action* action = actions[i].Action(); aWriter.Write("<action>"); aWriter.Write("<name>"); aWriter.Write(action->Name()); aWriter.Write("</name>"); aWriter.Write("<argumentList>"); WriteServiceActionParams(aWriter, *action, true); WriteServiceActionParams(aWriter, *action, false); aWriter.Write("</argumentList>"); aWriter.Write("</action>"); } aWriter.Write("</actionList>"); aWriter.Write("<serviceStateTable>"); const std::vector<Property*>& properties = aService.Properties(); for (TUint i=0; i<properties.size(); i++) { WriteStateVariable(aWriter, properties[i]->Parameter(), true, 0); } for (TUint i=0; i<actions.size(); i++) { const Action* action = actions[i].Action(); WriteTechnicalStateVariables(aWriter, action, action->InputParameters()); WriteTechnicalStateVariables(aWriter, action, action->OutputParameters()); } aWriter.Write("</serviceStateTable>"); aWriter.Write("</scpd>"); }
TUint CpiDeviceDv::Subscribe(CpiSubscription& aSubscription, const OpenHome::Uri& /*aSubscriber*/) { Brh sid; iDeviceDv.CreateSid(sid); Brn tmp(sid); Brh transfer(tmp); aSubscription.SetSid(transfer); TUint durationSecs = iDeviceCp->GetCpStack().Env().InitParams()->SubscriptionDurationSecs(); DviSubscription* subscriptionDv = new DviSubscription(iDeviceDv.GetDvStack(), iDeviceDv, *this, NULL, sid); subscriptionDv->AddRef(); // guard against subscription expiring before client tries to renew or unsubscribe iDeviceDv.GetDvStack().SubscriptionManager().AddSubscription(*subscriptionDv); subscriptionDv->SetDuration(durationSecs); iLock.Wait(); if (iSubscriptions.size() == 0) { iShutdownSem.Wait(); // consume shutdown signal now the map is non-empty } Brn sid2(subscriptionDv->Sid()); Subscription* subscription = new Subscription(aSubscription, subscriptionDv); iSubscriptions.insert(std::pair<Brn,Subscription*>(sid2, subscription)); iDeviceCp->AddRef(); iLock.Signal(); DviService* service = iDeviceDv.ServiceReference(aSubscription.ServiceType()); ASSERT(service != NULL); service->AddSubscription(subscriptionDv); service->RemoveRef(); return durationSecs; }
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); }
void DviSubscription::Remove() { iLock.Wait(); DviService* service = iService; if (service != NULL) { service->AddRef(); } iLock.Signal(); if (service != NULL) { service->RemoveSubscription(iSid); service->RemoveRef(); } }
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(); }
void CpiDeviceDv::InvokeAction(Invocation& aInvocation) { const OpenHome::Net::ServiceType& serviceType = aInvocation.ServiceType(); DviService* service = iDeviceDv.ServiceReference(serviceType); if (service == NULL) { const HttpStatus& err = HttpStatus::kNotFound; aInvocation.SetError(Error::eUpnp, err.Code(), err.Reason()); } else { InvocationDv stream(aInvocation, *service); stream.Start(); service->RemoveRef(); } aInvocation.SignalCompleted(); }
void CpiDeviceDv::Invocable::InvokeAction(Invocation& aInvocation) { const OpenHome::Net::ServiceType& serviceType = aInvocation.ServiceType(); DviService* service = iDevice.iDeviceDv.ServiceReference(serviceType); if (service == NULL) { LOG2(kCpDeviceDv, kError, "CpiDeviceDv::Invocable::InvokeAction failed lookup for service %.*s:%.*s:%u\n", PBUF(serviceType.Domain()), PBUF(serviceType.Name()), serviceType.Version()); const HttpStatus& err = HttpStatus::kNotFound; aInvocation.SetError(Error::eUpnp, err.Code(), err.Reason()); } else { InvocationDv stream(aInvocation, *service); stream.Start(); service->RemoveRef(); } }
DviService* DviDevice::ServiceReference(const ServiceType& aServiceType) { DviService* service = NULL; iServiceLock.Wait(); const Brx& fullNameUpnp = aServiceType.FullNameUpnp(); const TUint count = (TUint)iServices.size(); for (TUint i=0; i<count; i++) { DviService* s = iServices[i]; if (s->ServiceType().FullNameUpnp() == fullNameUpnp) { s->AddRef(); service = s; break; } } iServiceLock.Signal(); return service; }
void CpiDeviceDv::Unsubscribe(CpiSubscription& aSubscription, const Brx& aSid) { iLock.Wait(); Brn sid(aSid); SubscriptionMap::iterator it = iSubscriptions.find(sid); if (it == iSubscriptions.end()) { iLock.Signal(); return; } Subscription* subscription = it->second; iLock.Signal(); DviService* service = iDeviceDv.ServiceReference(aSubscription.ServiceType()); if (service != NULL) { service->RemoveSubscription(aSid); service->RemoveRef(); } subscription->iCp = NULL; subscription->iDv->RemoveRef(); // can't safely access subscription now - RemoveRef() above may have resulted in it being deleted }
void DviSessionUpnp::Unsubscribe() { LOG(kDvEvent, "Unsubscribe request: "); LOG(kDvEvent, iHeaderSid.Sid()); LOG(kDvEvent, "\n"); if (!iHeaderSid.Received()) { LOG2(kDvEvent, kError, "Unsubscribe failed - no sid\n"); Error(HttpStatus::kPreconditionFailed); } DviDevice* device; DviService* service; ParseRequestUri(DviProtocolUpnp::kEventUrlTail, &device, &service); if (device == NULL || service == NULL) { LOG2(kDvEvent, kError, "Unsubscribe failed - device=%p, service=%p\n", device, service); Error(HttpStatus::kPreconditionFailed); } DviSubscription* subscription = DviSubscriptionManager::Find(iHeaderSid.Sid()); if (subscription == NULL) { LOG2(kDvEvent, kError, "Unsubscribe failed - couldn't match sid "); LOG2(kDvEvent, kError, iHeaderSid.Sid()); LOG2(kDvEvent, kError, "\n"); Error(HttpStatus::kPreconditionFailed); } service->RemoveSubscription(iHeaderSid.Sid()); if (iHeaderExpect.Continue()) { iWriterResponse->WriteStatus(HttpStatus::kContinue, Http::eHttp11); iWriterResponse->WriteFlush(); } iResponseStarted = true; iWriterResponse->WriteStatus(HttpStatus::kOk, Http::eHttp11); iWriterResponse->WriteHeader(Http::kHeaderConnection, Http::kConnectionClose); iWriterResponse->WriteFlush(); iResponseEnded = true; LOG(kDvEvent, "Unsubscribe complete: "); LOG(kDvEvent, iHeaderSid.Sid()); LOG(kDvEvent, "\n"); }
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); }
TBool DviSessionLpec::SubscriptionData::Matches(DviDevice& aDevice, DviService& aService) const { return (iDevice->Udn() == aDevice.Udn() && iService->ServiceType().FullName() == aService.ServiceType().FullName()); }