void HttpInterface::evSubscribe(HttpRequest* req, strings& args) { // eventSubscriptions[conn] is an unordered set of strings if (args.size() == 1) eventSubscriptions[req].insert("*"); else for (strings::iterator i = args.begin()+1; i != args.end(); ++i) eventSubscriptions[req].insert(*i); strings headers; headers.push_back("Content-Type: text/event-stream"); headers.push_back("Cache-Control: no-cache"); headers.push_back("Connection: keep-alive"); addHeaders(req, headers); appendResponse(req,200,true,""); // connection must stay open! }
// Incoming User Messages void HttpInterface::incomingUserMsg(const UserMessage *userMsg) { if (verbose) cerr << "incomingUserMsg msg ("<< userMsg->type <<","<< &userMsg->data <<")" << endl; // skip if event not known (yet, aesl probably not loaded) try { commonDefinitions.events.at(userMsg->type); } catch (const std::out_of_range& oor) { return; } if (commonDefinitions.events[userMsg->type].name.find(L"R_state")==0) { // update variables } if (eventSubscriptions.size() > 0) { // set up SSE message std::stringstream reply; string event_name = WStringToUTF8(commonDefinitions.events[userMsg->type].name); reply << "data: " << event_name; for (size_t i = 0; i < userMsg->data.size(); ++i) reply << " " << userMsg->data[i]; reply << "\r\n\r\n"; // In the HTTP world we set up a stream of Server-Sent Events for this. // Note that event name is in commonDefinitions.events[userMsg->type].name for (StreamEventSubscriptionMap::iterator subscriber = eventSubscriptions.begin(); subscriber != eventSubscriptions.end(); ++subscriber) { if (subscriber->second.count("*") >= 1 || subscriber->second.count(event_name) >= 1) { appendResponse(subscriber->first, 200, true, reply.str().c_str()); } } } }
void TTscriptBase::addResponse(int id) { appendResponse(-1, nullptr, id); }