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 DviSubscriptionManager::AddSubscription(DviSubscription& aSubscription) { iLock.Wait(); Brn sid(aSubscription.Sid()); iMap.insert(std::pair<Brn,DviSubscription*>(sid, &aSubscription)); aSubscription.AddRef(); iLock.Signal(); }
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 DviService::StopSubscriptions() { iLock.Wait(); for (TUint i=0; i<iSubscriptions.size(); i++) { DviSubscription* subscription = iSubscriptions[i]; subscription->Stop(); iDvStack.SubscriptionManager().RemoveSubscription(*subscription); subscription->RemoveRef(); } iSubscriptions.clear(); iLock.Signal(); }
DviSubscription* DviSubscriptionManager::Find(const Brx& aSid) { DviSubscription* subs = NULL; iLock.Wait(); Brn sid(aSid); Map::iterator it = iMap.find(sid); if (it != iMap.end()) { subs = it->second; subs->AddRef(); } iLock.Signal(); return subs; }
void DviService::RemoveSubscription(const Brx& aSid) { iLock.Wait(); for (TUint i=0; i<iSubscriptions.size(); i++) { DviSubscription* subscription = iSubscriptions[i]; if (subscription->Sid() == aSid) { DviSubscriptionManager::RemoveSubscription(*subscription); iSubscriptions.erase(iSubscriptions.begin() + i); iLock.Signal(); subscription->RemoveRef(); return; } } iLock.Signal(); }
void DviProviderSubscriptionLongPoll::Renew(IDvInvocation& aInvocation, const Brx& aSid, TUint aRequestedDuration, IDvInvocationResponseUint& aDuration) { DviSubscription* subscription = iDvStack.SubscriptionManager().Find(aSid); if (subscription == NULL) { aInvocation.Error(kErrorCodeBadSubscription, kErrorDescBadSubscription); } TUint timeout = aRequestedDuration; if (timeout > kTimeoutLongPollSecs) { timeout = kTimeoutLongPollSecs; } subscription->Renew(timeout); aInvocation.StartResponse(); aDuration.Write(timeout); aInvocation.EndResponse(); }
void PropertyWriterFactory::SubscriptionAdded(DviSubscription& aSubscription) { iSubscriptionMapLock.Wait(); Brn sidBuf(aSubscription.Sid()); iSubscriptionMap.insert(std::pair<Brn,DviSubscription*>(sidBuf, &aSubscription)); iSubscriptionMapLock.Signal(); AddRef(); }
void DviSubscriptionManager::QueueUpdate(DviSubscription& aSubscription) { aSubscription.AddRef(); iLock.Wait(); iList.push_back(&aSubscription); Signal(); iLock.Signal(); }
DviService::~DviService() { iLock.Wait(); TUint i=0; for (; i<iSubscriptions.size(); i++) { DviSubscription* subscription = iSubscriptions[i]; DviSubscriptionManager::RemoveSubscription(*subscription); subscription->RemoveRef(); } for (i=0; i<iDvActions.size(); i++) { delete iDvActions[i].Action(); } for (i=0; i<iProperties.size(); i++) { delete iProperties[i]; } iLock.Signal(); Stack::RemoveObject(this, "DviService"); }
void PropertyUpdatesFlattened::RemoveSubscription(const Brx& aSid, TBool aExpired) { Brn sid(aSid); SubscriptionMap::iterator it = iSubscriptionMap.find(sid); if (it != iSubscriptionMap.end()) { // remove any pending updates for this subscription too UpdatesMap::iterator it2 = iUpdatesMap.find(sid); if (it2 != iUpdatesMap.end()) { delete it2->second; iUpdatesMap.erase(it2); } DviSubscription* subscription = it->second; iSubscriptionMap.erase(it); if (!aExpired) { subscription->Remove(); } } }
void DviSessionUpnp::Renew() { LOG(kDvEvent, "Renew subscription (request): "); LOG(kDvEvent, iHeaderSid.Sid()); LOG(kDvEvent, "for %u secs\n", iHeaderTimeout.Timeout()); if (iHeaderCallback.Received() || iHeaderNt.Received()) { Error(HttpStatus::kBadRequest); } DviDevice* device; DviService* service; ParseRequestUri(DviProtocolUpnp::kEventUrlTail, &device, &service); if (device == NULL || service == NULL) { Error(HttpStatus::kPreconditionFailed); } DviSubscription* subscription = DviSubscriptionManager::Find(iHeaderSid.Sid()); if (subscription == NULL) { Error(HttpStatus::kPreconditionFailed); } TUint duration = iHeaderTimeout.Timeout(); subscription->Renew(duration); iResponseStarted = true; iWriterResponse->WriteStatus(HttpStatus::kOk, Http::eHttp11); WriteServerHeader(*iWriterResponse); IWriterAscii& writerSid = iWriterResponse->WriteHeaderField(HeaderSid::kHeaderSid); writerSid.Write(HeaderSid::kFieldSidPrefix); writerSid.Write(iHeaderSid.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, "Renew subscription (complete): "); LOG(kDvEvent, iHeaderSid.Sid()); LOG(kDvEvent, "for %u secs\n", duration); }
void DviSubscriptionManager::RemoveSubscription(DviSubscription& aSubscription) { iLock.Wait(); Brn sid(aSubscription.Sid()); Map::iterator it = iMap.find(sid); if (it != iMap.end()) { iMap.erase(it); } iLock.Signal(); }
void DviSessionLpec::DoUnsubscribe(TUint aIndex, TBool aRespond) { DviSubscription* subscription = iSubscriptions[aIndex].Subscription(); ASSERT(subscription != NULL); iSubscriptions[aIndex].Service().RemoveSubscription(subscription->Sid()); if (aRespond) { AutoMutex a(iWriteLock); iResponseStarted = true; iWriteBuffer->Write(Lpec::kMethodUnsubscribe); iWriteBuffer->Write(' '); Bws<Ascii::kMaxUintStringBytes> lpecSidBuf; (void)Ascii::AppendDec(lpecSidBuf, iSubscriptions[aIndex].LpecSid()); iWriteBuffer->Write(lpecSidBuf); iWriteBuffer->Write(Lpec::kMsgTerminator); iWriteBuffer->WriteFlush(); iResponseEnded = true; } iSubscriptions.erase(iSubscriptions.begin()+aIndex); }
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); }
void PropertyWriterFactory::Disable() { Stack::Mutex().Wait(); iEnabled = false; Stack::Mutex().Signal(); iSubscriptionMapLock.Wait(); std::vector<DviSubscription*> subscriptions; SubscriptionMap::iterator it = iSubscriptionMap.begin(); if (it != iSubscriptionMap.end()) { DviSubscription* subscription = it->second; if (subscription->TryAddRef()) { subscriptions.push_back(subscription); } it++; } iSubscriptionMapLock.Signal(); for (TUint i=0; i<(TUint)subscriptions.size(); i++) { DviSubscription* subscription = subscriptions[i]; subscription->Remove(); subscription->RemoveRef(); } RemoveRef(); }