void ListenerService::receive(DDF &in, ostream& out) { if (!in.name()) throw ListenerException("Incoming message with no destination address rejected."); else if (!strcmp("ping",in.name())) { DDF outmsg=DDF(NULL).integer(in.integer() + 1); DDFJanitor jan(outmsg); out << outmsg; } Locker locker(SPConfig::getConfig().getServiceProvider()); Remoted* dest=lookup(in.name()); if (!dest) throw ListenerException("No destination registered for incoming message addressed to ($1).",params(1,in.name())); dest->receive(in, out); }
DDF XMLAttribute::marshall() const { DDF ddf = Attribute::marshall(); ddf.name("XML"); DDF vlist = ddf.first(); for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) vlist.add(DDF(NULL).string(i->c_str())); return ddf; }
void ListenerService::receive(DDF &in, ostream& out) { if (!in.name()) throw ListenerException("Incoming message with no destination address rejected."); else if (!strcmp("ping", in.name())) { DDF outmsg = DDF(nullptr).integer(in.integer() + 1); DDFJanitor jan(outmsg); out << outmsg; return; } else if (!strcmp("hash", in.name())) { #ifndef SHIBSP_LITE const char* hashAlg = in["alg"].string(); const char* data = in["data"].string(); if (!hashAlg || !*hashAlg || !data || !*data) throw ListenerException("Hash request missing algorithm or data parameters."); DDF outmsg(nullptr); DDFJanitor jan(outmsg); outmsg.string(SecurityHelper::doHash(hashAlg, data, strlen(data)).c_str()); out << outmsg; return; #else throw ListenerException("Hash algorithms unavailable in lite build of library."); #endif } // Two stage lookup, on the listener itself, and the SP interface. ServiceProvider* sp = SPConfig::getConfig().getServiceProvider(); Locker locker(sp); Remoted* dest = lookup(in.name()); if (!dest) { dest = sp->lookupListener(in.name()); if (!dest) throw ListenerException("No destination registered for incoming message addressed to ($1).", params(1,in.name())); } dest->receive(in, out); }
void Application::clearAttributeHeaders(SPRequest& request) const { if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i) request.clearHeader(i->first.c_str(), i->second.c_str()); return; } m_lock->rdlock(); if (m_unsetHeaders.empty()) { // No headers yet, so we have to request them from the remote half. m_lock->unlock(); m_lock->wrlock(); if (m_unsetHeaders.empty()) { SharedLock wrlock(m_lock, false); string addr=string(getId()) + "::getHeaders::Application"; DDF out,in = DDF(addr.c_str()); DDFJanitor jin(in),jout(out); out = getServiceProvider().getListenerService()->send(in); if (out.islist()) { DDF header = out.first(); while (header.isstring()) { m_unsetHeaders.push_back(pair<string,string>(header.name(),header.string())); header = out.next(); } } } else { m_lock->unlock(); } m_lock->rdlock(); } // Now holding read lock. SharedLock unsetLock(m_lock, false); for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i) request.clearHeader(i->first.c_str(), i->second.c_str()); }
int ServerThread::job() { Category& log = Category::getInstance("shibd.Listener"); bool incomingError = true; // set false once incoming message is received ostringstream sink; #ifdef WIN32 u_long len; #else uint32_t len; #endif try { // Read the message. int readlength = m_listener->recv(m_sock,(char*)&len,sizeof(len)); if (readlength == 0) { log.info("detected socket closure, shutting down worker thread"); return 1; } else if (readlength != sizeof(len)) { log.error("error reading size of input message"); return -1; } len = ntohl(len); int size_read; stringstream is; while (len && (size_read = m_listener->recv(m_sock, m_buf, sizeof(m_buf))) > 0) { is.write(m_buf, size_read); len -= size_read; } if (len) { log.error("error reading input message from socket"); return -1; } // Unmarshall the message. DDF in; DDFJanitor jin(in); is >> in; log.debug("dispatching message (%s)", in.name() ? in.name() : "unnamed"); incomingError = false; // Dispatch the message. m_listener->receive(in, sink); } catch (XMLToolingException& e) { if (incomingError) log.error("error processing incoming message: %s", e.what()); DDF out=DDF("exception").string(e.toString().c_str()); DDFJanitor jout(out); sink << out; } catch (exception& e) { if (incomingError) log.error("error processing incoming message: %s", e.what()); ListenerException ex(e.what()); DDF out=DDF("exception").string(ex.toString().c_str()); DDFJanitor jout(out); sink << out; } catch (...) { if (incomingError) log.error("unexpected error processing incoming message"); if (!m_listener->m_catchAll) throw; ListenerException ex("An unexpected error occurred while processing an incoming message."); DDF out=DDF("exception").string(ex.toString().c_str()); DDFJanitor jout(out); sink << out; } // Return whatever's available. string response(sink.str()); int outlen = response.length(); len = htonl(outlen); if (m_listener->send(m_sock,(char*)&len,sizeof(len)) != sizeof(len)) { log.error("error sending output message size"); return -1; } if (m_listener->send(m_sock,response.c_str(),outlen) != outlen) { log.error("error sending output message"); return -1; } return 0; }
DDF SocketListener::send(const DDF& in) { #ifdef _DEBUG NDC ndc("send"); #endif log->debug("sending message (%s)", in.name() ? in.name() : "unnamed"); // Serialize data for transmission. ostringstream os; os << in; string ostr(os.str()); // Loop on the RPC in case we lost contact the first time through #ifdef WIN32 u_long len; #else uint32_t len; #endif int retry = 1; SocketListener::ShibSocket sock; while (retry >= 0) { sock = m_socketpool->get(); int outlen = ostr.length(); len = htonl(outlen); if (send(sock,(char*)&len,sizeof(len)) != sizeof(len) || send(sock,ostr.c_str(),outlen) != outlen) { log_error(); this->close(sock); if (retry) retry--; else throw ListenerException("Failure sending remoted message ($1).", params(1,in.name())); } else { // SUCCESS. retry = -1; } } log->debug("send completed, reading response message"); // Read the message. if (recv(sock,(char*)&len,sizeof(len)) != sizeof(len)) { log->error("error reading size of output message"); this->close(sock); throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name())); } len = ntohl(len); char buf[16384]; int size_read; stringstream is; while (len && (size_read = recv(sock, buf, sizeof(buf))) > 0) { is.write(buf, size_read); len -= size_read; } if (len) { log->error("error reading output message from socket"); this->close(sock); throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name())); } m_socketpool->put(sock); // Unmarshall data. DDF out; is >> out; // Check for exception to unmarshall and throw, otherwise return. if (out.isstring() && out.name() && !strcmp(out.name(),"exception")) { // Reconstitute exception object. DDFJanitor jout(out); XMLToolingException* except=NULL; try { except=XMLToolingException::fromString(out.string()); log->error("remoted message returned an error: %s", except->what()); } catch (XMLToolingException& e) { log->error("caught XMLToolingException while building the XMLToolingException: %s", e.what()); log->error("XML was: %s", out.string()); throw ListenerException("Remote call failed with an unparsable exception."); } auto_ptr<XMLToolingException> wrapper(except); wrapper->raise(); } return out; }