#include "internal.h"
#include "exceptions.h"
+#include "ServiceProvider.h"
#include "remoting/impl/SocketListener.h"
#include <errno.h>
#include <shibsp/SPConfig.h>
#include <xmltooling/util/NDC.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
+#ifndef WIN32
+# include <netinet/in.h>
#endif
using namespace shibsp;
using namespace xmltooling;
-using namespace log4cpp;
using namespace std;
using xercesc::DOMElement;
private:
SocketListener::ShibSocket connect();
-
+
+ Category& m_log;
const SocketListener* m_listener;
- Category& m_log;
auto_ptr<Mutex> m_lock;
stack<SocketListener::ShibSocket> m_pool;
};
ServerThread(SocketListener::ShibSocket& s, SocketListener* listener, unsigned long id);
~ServerThread();
void run();
- bool job();
+ int job(); // Return -1 on error, 1 for closed, 0 for success
private:
SocketListener::ShibSocket m_sock;
m_lock->unlock();
}
-SocketListener::SocketListener(const DOMElement* e) : log(&Category::getInstance(SHIBSP_LOGCAT".Listener")),
- m_shutdown(NULL), m_child_lock(NULL), m_child_wait(NULL), m_socketpool(NULL), m_socket((ShibSocket)0)
+SocketListener::SocketListener(const DOMElement* e) : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")),
+ m_socketpool(NULL), m_shutdown(NULL), m_child_lock(NULL), m_child_wait(NULL), m_socket((ShibSocket)0)
{
// Are we a client?
if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
#ifdef _DEBUG
NDC ndc("run");
#endif
-
+ log->info("listener service starting");
+
+ ServiceProvider* sp = SPConfig::getConfig().getServiceProvider();
+ sp->lock();
+ const PropertySet* props = sp->getPropertySet("OutOfProcess");
+ if (props) {
+ pair<bool,bool> flag = props->getBool("catchAll");
+ m_catchAll = flag.first && flag.second;
+ }
+ sp->unlock();
+
// Save flag to monitor for shutdown request.
m_shutdown=shutdown;
unsigned long count = 0;
}
catch (...) {
log->crit("error starting new server thread to service incoming request");
+ if (!m_catchAll)
+ *m_shutdown = true;
}
}
}
NDC ndc("send");
#endif
- log->debug("sending message: %s", in.name());
+ log->debug("sending message (%s)", in.name() ? in.name() : "unnamed");
// Serialize data for transmission.
ostringstream os;
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());
m_listener->m_children[m_sock] = m_child;
m_listener->m_child_lock->unlock();
+ int result;
fd_set readfds;
struct timeval tv = { 0, 0 };
break;
default:
- if (!job()) {
- m_listener->log_error();
- m_listener->log->error("I/O failure processing request on socket (%u)", m_sock);
+ result = job();
+ if (result) {
+ if (result < 0) {
+ m_listener->log_error();
+ m_listener->log->error("I/O failure processing request on socket (%u)", m_sock);
+ }
m_listener->close(m_sock);
return;
}
}
}
-bool ServerThread::job()
+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;
try {
// Read the message.
- if (m_listener->recv(m_sock,(char*)&len,sizeof(len)) != sizeof(len)) {
+ 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 false;
+ return -1;
}
len = ntohl(len);
if (len) {
log.error("error reading input message from socket");
- return false;
+ return -1;
}
// Unmarshall the message.
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) {
- log.error("error processing incoming message: %s", e.what());
+ 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) {
- log.error("error processing incoming message: %s", e.what());
+ 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;
}
-#ifndef _DEBUG
catch (...) {
- log.error("unexpected error processing incoming message");
+ 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;
}
-#endif
// Return whatever's available.
string response(sink.str());
len = htonl(outlen);
if (m_listener->send(m_sock,(char*)&len,sizeof(len)) != sizeof(len)) {
log.error("error sending output message size");
- return false;
+ return -1;
}
if (m_listener->send(m_sock,response.c_str(),outlen) != outlen) {
log.error("error sending output message");
- return false;
+ return -1;
}
- return true;
+ return 0;
}