10 #include "xmlrpc-c/girerr.hpp"
13 #include "xmlrpc-c/base.h"
14 #include "xmlrpc-c/base.hpp"
15 #include "xmlrpc-c/server_abyss.h"
16 #include "xmlrpc-c/registry.hpp"
17 #include "xmlrpc-c/server_abyss.hpp"
20 using namespace xmlrpc_c;
28 sigterm(int const signalClass) {
30 cerr << "Signal of Class " << signalClass << " received. Exiting" << endl;
38 sigchld(int const signalClass) {
39 /*----------------------------------------------------------------------------
40 This is a signal handler for a SIGCHLD signal (which informs us that
41 one of our child processes has terminated).
43 We respond by reaping the zombie process.
45 Implementation note: In some systems, just setting the signal handler
46 to SIG_IGN (ignore signal) does this. In others, it doesn't.
47 -----------------------------------------------------------------------------*/
49 /* Reap zombie children until there aren't any more. */
54 assert(signalClass == SIGCHLD);
56 zombiesExist = true; // initial assumption
57 error = false; // no error yet
58 while (zombiesExist && !error) {
60 pid_t const pid = waitpid((pid_t) -1, &status, WNOHANG);
65 /* because of ptrace */
67 // This is OK - it's a ptrace notification
78 setupSignalHandlers(void) {
80 struct sigaction mysigaction;
82 sigemptyset(&mysigaction.sa_mask);
83 mysigaction.sa_flags = 0;
85 /* These signals abort the program, with tracing */
86 mysigaction.sa_handler = sigterm;
87 sigaction(SIGTERM, &mysigaction, NULL);
88 sigaction(SIGINT, &mysigaction, NULL);
89 sigaction(SIGHUP, &mysigaction, NULL);
90 sigaction(SIGUSR1, &mysigaction, NULL);
92 /* This signal indicates connection closed in the middle */
93 mysigaction.sa_handler = SIG_IGN;
94 sigaction(SIGPIPE, &mysigaction, NULL);
96 /* This signal indicates a child process (request handler) has died */
97 mysigaction.sa_handler = sigchld;
98 sigaction(SIGCHLD, &mysigaction, NULL);
107 serverAbyss::constrOpt::constrOpt() {
108 present.registryPtr = false;
109 present.registryP = false;
110 present.socketFd = false;
111 present.portNumber = false;
112 present.logFileName = false;
113 present.keepaliveTimeout = false;
114 present.keepaliveMaxConn = false;
115 present.timeout = false;
116 present.dontAdvertise = false;
117 present.uriPath = false;
118 present.chunkResponse = false;
120 // Set default values
121 value.dontAdvertise = false;
122 value.uriPath = string("/RPC2");
123 value.chunkResponse = false;
128 #define DEFINE_OPTION_SETTER(OPTION_NAME, TYPE) \
129 serverAbyss::constrOpt & \
130 serverAbyss::constrOpt::OPTION_NAME(TYPE const& arg) { \
131 this->value.OPTION_NAME = arg; \
132 this->present.OPTION_NAME = true; \
136 DEFINE_OPTION_SETTER(registryPtr, xmlrpc_c::registryPtr);
137 DEFINE_OPTION_SETTER(registryP, const registry *);
138 DEFINE_OPTION_SETTER(socketFd, xmlrpc_socket);
139 DEFINE_OPTION_SETTER(portNumber, uint);
140 DEFINE_OPTION_SETTER(logFileName, string);
141 DEFINE_OPTION_SETTER(keepaliveTimeout, uint);
142 DEFINE_OPTION_SETTER(keepaliveMaxConn, uint);
143 DEFINE_OPTION_SETTER(timeout, uint);
144 DEFINE_OPTION_SETTER(dontAdvertise, bool);
145 DEFINE_OPTION_SETTER(uriPath, string);
146 DEFINE_OPTION_SETTER(chunkResponse, bool);
151 serverAbyss::setAdditionalServerParms(constrOpt const& opt) {
153 /* The following ought to be parameters on ServerCreate(), but it
154 looks like plugging them straight into the TServer structure is
155 the only way to set them.
158 if (opt.present.keepaliveTimeout)
159 ServerSetKeepaliveTimeout(&this->cServer, opt.value.keepaliveTimeout);
160 if (opt.present.keepaliveMaxConn)
161 ServerSetKeepaliveMaxConn(&this->cServer, opt.value.keepaliveMaxConn);
162 if (opt.present.timeout)
163 ServerSetTimeout(&this->cServer, opt.value.timeout);
164 ServerSetAdvertise(&this->cServer, !opt.value.dontAdvertise);
170 createServer(bool const logFileNameGiven,
171 string const& logFileName,
172 bool const socketFdGiven,
174 bool const portNumberGiven,
175 unsigned int const portNumber,
176 TServer * const srvPP) {
178 const char * const logfileArg(logFileNameGiven ?
179 logFileName.c_str() : NULL);
181 const char * const serverName("XmlRpcServer");
187 ServerCreateSocket(srvPP, serverName, socketFd,
188 DEFAULT_DOCS, logfileArg);
189 else if (portNumberGiven) {
190 if (portNumber > 0xffff)
191 throwf("Port number %u exceeds the maximum possible port number "
192 "(65535)", portNumber);
195 ServerCreate(srvPP, serverName, portNumber,
196 DEFAULT_DOCS, logfileArg);
199 ServerCreateNoAccept(srvPP, serverName,
200 DEFAULT_DOCS, logfileArg);
203 throw(error("Failed to create Abyss server. See Abyss error log for "
210 serverAbyss::initialize(constrOpt const& opt) {
212 const registry * registryP;
214 if (!opt.present.registryP && !opt.present.registryPtr)
215 throwf("You must specify the 'registryP' or 'registryPtr' option");
216 else if (opt.present.registryP && opt.present.registryPtr)
217 throwf("You may not specify both the 'registryP' and "
218 "the 'registryPtr' options");
220 if (opt.present.registryP)
221 registryP = opt.value.registryP;
223 this->registryPtr = opt.value.registryPtr;
224 registryP = this->registryPtr.get();
227 if (opt.present.portNumber && opt.present.socketFd)
228 throwf("You can't specify both portNumber and socketFd options");
232 createServer(opt.present.logFileName, opt.value.logFileName,
233 opt.present.socketFd, opt.value.socketFd,
234 opt.present.portNumber, opt.value.portNumber,
238 setAdditionalServerParms(opt);
240 // chunked response implementation is incomplete. We must
241 // eventually get away from libxmlrpc_server_abyss and
242 // register our own handler with the Abyss server. At that
243 // time, we'll have some place to pass
244 // opt.value.chunkResponse.
246 xmlrpc_c::server_abyss_set_handlers(&this->cServer,
250 if (opt.present.portNumber || opt.present.socketFd)
251 ServerInit(&this->cServer);
253 setupSignalHandlers();
255 ServerFree(&this->cServer);
262 serverAbyss::serverAbyss(constrOpt const& opt) {
269 serverAbyss::serverAbyss(
270 xmlrpc_c::registry const& registry,
271 unsigned int const portNumber,
272 string const& logFileName,
273 unsigned int const keepaliveTimeout,
274 unsigned int const keepaliveMaxConn,
275 unsigned int const timeout,
276 bool const dontAdvertise,
277 bool const socketBound,
278 xmlrpc_socket const socketFd) {
279 /*----------------------------------------------------------------------------
280 This is a backward compatibility interface. This used to be the only
282 -----------------------------------------------------------------------------*/
283 serverAbyss::constrOpt opt;
285 opt.registryP(®istry);
286 if (logFileName.length() > 0)
287 opt.logFileName(logFileName);
288 if (keepaliveTimeout > 0)
289 opt.keepaliveTimeout(keepaliveTimeout);
290 if (keepaliveMaxConn > 0)
291 opt.keepaliveMaxConn(keepaliveMaxConn);
293 opt.timeout(timeout);
294 opt.dontAdvertise(dontAdvertise);
296 opt.socketFd(socketFd);
298 opt.portNumber(portNumber);
305 serverAbyss::~serverAbyss() {
307 ServerFree(&this->cServer);
315 ServerRun(&this->cServer);
321 serverAbyss::runOnce() {
323 ServerRunOnce(&this->cServer);
329 serverAbyss::runConn(int const socketFd) {
331 ServerRunConn(&this->cServer, socketFd);
337 server_abyss_set_handlers(TServer * const srvP,
338 registry const& registry,
339 string const& uriPath) {
341 xmlrpc_server_abyss_set_handlers2(srvP,
343 registry.c_registry());
349 server_abyss_set_handlers(TServer * const srvP,
350 const registry * const registryP,
351 string const& uriPath) {
353 xmlrpc_server_abyss_set_handlers2(srvP,
355 registryP->c_registry());
361 server_abyss_set_handlers(TServer * const srvP,
362 registryPtr const registryPtr,
363 string const& uriPath) {
365 xmlrpc_server_abyss_set_handlers2(srvP,
367 registryPtr->c_registry());