/*\r
- * Copyright 2001-2007 Internet2\r
+ * Copyright 2001-2009 Internet2\r
*\r
* Licensed under the Apache License, Version 2.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
const char* shar_prefix = NULL;\r
bool shar_checkonly = false;\r
bool shar_version = false;\r
-static int unlink_socket = 0;\r
+static bool unlink_socket = false;\r
const char* pidfile = NULL;\r
\r
#ifdef WIN32\r
\r
//_CrtSetAllocHook(MyAllocHook);\r
\r
- // Run the listener\r
if (!shar_checkonly) {\r
-\r
// Run the listener.\r
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
+ if (!conf.getServiceProvider()->getListenerService()->run(unlink_socket, &shibd_shutdown)) {\r
fprintf(stderr, "listener failed to enter listen loop\n");\r
return -3;\r
}\r
shar_schemadir=optarg;\r
break;\r
case 'f':\r
- unlink_socket = 1;\r
+ unlink_socket = true;\r
break;\r
case 't':\r
shar_checkonly=true;\r
if (shar_checkonly)\r
fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
else {\r
-\r
// Write the pid file\r
if (pidfile) {\r
FILE* pidf = fopen(pidfile, "w");\r
}\r
\r
// Run the listener\r
- if (!conf.getServiceProvider()->getListenerService()->run(&shibd_shutdown)) {\r
+ if (!conf.getServiceProvider()->getListenerService()->run(unlink_socket, &shibd_shutdown)) {\r
fprintf(stderr, "listener failed to enter listen loop\n");\r
return -3;\r
}\r
virtual Remoted* lookup(const char* address) const;
/**
+ * @deprecated
* OutOfProcess servers can implement server-side transport handling by
* calling the run method and supplying a flag to monitor for shutdown.
*
*/
virtual bool run(bool* shutdown)=0;
+ /**
+ * OutOfProcess servers can implement server-side transport handling by
+ * calling the run method and supplying a flag to monitor for shutdown.
+ *
+ * <p>The first parameter applies to implementations that can detect and remove
+ * the results of ungraceful shutdowns of previous executions and continue
+ * successfully. File-based sockets are the most common example.
+ *
+ * @param force true iff remnant network state should be forcibly cleared
+ * @param shutdown pointer to flag that caller will set when shutdown is required
+ * @return true iff the service execution was successful
+ */
+ virtual bool run(bool force, bool* shutdown);
+
private:
std::map<std::string,Remoted*> m_listenerMap;
};
/*
* Copyright 2001-2009 Internet2
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
/**
* SocketListener.cpp
- *
+ *
* Berkeley Socket-based ListenerService implementation
*/
using xercesc::DOMElement;
namespace shibsp {
-
+
// Manages the pool of connections
class SocketPool
{
~SocketPool();
SocketListener::ShibSocket get();
void put(SocketListener::ShibSocket s);
-
+
private:
SocketListener::ShibSocket connect();
-
- Category& m_log;
+
+ Category& m_log;
const SocketListener* m_listener;
auto_ptr<Mutex> m_lock;
stack<SocketListener::ShibSocket> m_pool;
};
-
+
// Worker threads in server
class ServerThread {
public:
connected = true;
break;
}
-
+
m_log.warn("cannot connect socket (%u)...%s", sock, (i > 0 ? "retrying" : ""));
if (i) {
delete m_child_lock;
}
-bool SocketListener::run(bool* shutdown)
+bool SocketListener::run(bool force, bool* shutdown)
{
#ifdef _DEBUG
NDC ndc("run");
m_catchAll = flag.first && flag.second;
}
sp->unlock();
-
+
// Save flag to monitor for shutdown request.
m_shutdown=shutdown;
unsigned long count = 0;
log->crit("failed to create socket");
return false;
}
- if (!bind(m_socket,true)) {
+ if (!bind(m_socket, force)) {
this->close(m_socket);
log->crit("failed to bind to socket.");
return false;
FD_SET(m_socket, &readfds);
struct timeval tv = { 0, 0 };
tv.tv_sec = 5;
-
+
switch (select(m_socket + 1, &readfds, 0, 0, &tv)) {
#ifdef WIN32
case SOCKET_ERROR:
log_error();
log->error("select() on main listener socket failed");
return false;
-
+
case 0:
continue;
-
+
default:
{
// Accept the connection.
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) {
throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
}
len = ntohl(len);
-
+
char buf[16384];
int size_read;
stringstream is;
break;
}
}
-
+
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 {
+ try {
except=XMLToolingException::fromString(out.string());
log->error("remoted message returned an error: %s", except->what());
}
m_listener->m_children.erase(m_sock);
m_listener->m_child_lock->unlock();
m_listener->m_child_wait->signal();
-
+
delete m_child;
}
m_listener->m_child_wait->wait(m_listener->m_child_lock);
m_listener->m_children[m_sock] = m_child;
m_listener->m_child_lock->unlock();
-
+
int result;
fd_set readfds;
struct timeval tv = { 0, 0 };
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);
DDFJanitor jout(out);
sink << out;
}
-
+
// Return whatever's available.
string response(sink.str());
int outlen = response.length();
log.error("error sending output message");
return -1;
}
-
+
return 0;
}
/*
- * Copyright 2001-2007 Internet2
+ * Copyright 2001-2009 Internet2
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* SocketListener.h
- *
+ *
* Berkeley Socket-based ListenerService implementation
*/
class SocketPool;
class ServerThread;
-
+
/**
* Berkeley Socket-based ListenerService implementation
*/
~SocketListener();
DDF send(const DDF& in);
- bool run(bool* shutdown);
+ bool run(bool* shutdown) {
+ return run(true, shutdown);
+ }
+ bool run(bool force, bool* shutdown);
// Implemented by socket-specific subclasses.
#ifdef WIN32
bool log_error() const; // for OS-level errors
xmltooling::logging::Category* log;
/// @endcond
-
+
private:
mutable SocketPool* m_socketpool;
bool* m_shutdown;