~SoapReplier() { // End of body -- assemble reply unsigned int rc = ENOSYS; soap::Params result; SoapInfo *soap_info = new SoapInfo; soap_info->ipe = m_ipe; soap_info->access = m_access; m_endpoints->reset(soap_info); rc = m_service->OnAction(m_action, m_args, &result); if (rc) { m_response->status_line = "HTTP/1.1 801 Error\r\n"; std::string body( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n" "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"" " s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n" " <s:Body>" " <s:Fault><faultcode>soap:Server</faultcode>" " <faultstring>Service error "); body += util::SPrintf("%u", rc); body += "</faultstring></s:Fault></s:Body></s:Envelope>\r\n"; LOG(SOAP) << "Soap response is " << body << "\n"; m_response->body_source.reset(new util::StringStream(body)); } else { std::string body = soap::CreateBody(m_service->GetData(), m_action, true, m_service->GetServiceType(), result); LOG(SOAP) << "Soap response is " << body << "\n"; m_response->body_source.reset(new util::StringStream(body)); } }
bool Server::Impl::StreamForPath(const util::http::Request *rq, util::http::Response *rs) { LOG(UPNP) << "Got " << rq->verb << " request for " << rq->path << "\n"; const char *path = rq->path.c_str(); const char *usn; if (rq->path == s_description_path) { LOG(UPNP) << "Serving description request\n"; rs->body_source.reset( new util::StringStream(Description(rq->local_ep.addr))); rs->content_type = "text/xml; charset=\"utf-8\""; return true; } else if (prefixcmp(path, "/upnp/event/", &usn)) { if (rq->verb == "SUBSCRIBE") { LOG(UPNP) << "I'm being subscribed at\n" << rq->headers; Service *service = FindService(usn); if (service) { std::string delivery = rq->GetHeader("callback"); if (delivery.size() > 2) { delivery.erase(0,1); delivery.erase(delivery.size()-1); m_subscriptions.push_back(Subscription(service, delivery)); rs->headers["SID"] = delivery; // why not? rs->headers["TIMEOUT"] = "infinite"; rs->body_source.reset(new util::StringStream("")); } } else { TRACE << "Can't find service " << usn << "\n"; } return true; } else if (rq->verb == "UNSUBSCRIBE") { LOG(UPNP) << "I'm being unsubscribed at\n" << rq->headers; Service *service = FindService(usn); if (service) { std::string delivery = rq->GetHeader("SID"); for (subscriptions_t::iterator i = m_subscriptions.begin(); i != m_subscriptions.end(); ++i) { if (i->service == service && i->delivery_url == delivery) { m_subscriptions.erase(i); LOG(UPNP) << "Found and erased subscription\n"; rs->body_source.reset(new util::StringStream("")); break; } } } return true; } } else if (prefixcmp(path, "/upnp/control/", &usn)) { if (rq->verb == "POST") { LOG(UPNP) << "I'm being soaped at\n" << rq->headers; Service *svc = FindService(usn); if (svc) { std::string action_name = rq->GetHeader("SOAPACTION"); if (!action_name.empty()) { action_name.erase(0,action_name.rfind('#')+1); action_name.erase(action_name.rfind('\"')); LOG(UPNP) << "Soap action: " << action_name << "\n"; const upnp::Data *data = svc->GetData(); unsigned int action = data->actions.Find(action_name.c_str()); if (action < data->actions.n) { rs->content_type = "text/xml; charset=\"utf-8\""; rs->body_sink.reset(new SoapReplier(svc, action, rs, rq->local_ep, rq->access, &m_endpoints)); return true; } else { LOG(UPNP) << "Action " << action_name << " not found\n"; } } } else { LOG(UPNP) << "Service " << usn << " not found\n"; } } } return false; }