version 1.3, 2015/04/20 18:10:20
|
version 1.4, 2015/04/20 18:20:13
|
|
|
| |
#include <limits.h> | #include <limits.h> |
#include <protocol/protocol.h> | #include <protocol/protocol.h> |
#include <base/time.h> |
#include <pal/sleep.h> |
#include <wsman/wsman.h> | #include <wsman/wsman.h> |
#include <provreg/provreg.h> | #include <provreg/provreg.h> |
#include <provmgr/provmgr.h> | #include <provmgr/provmgr.h> |
#include <disp/disp.h> | #include <disp/disp.h> |
#include <base/strings.h> |
#include <pal/strings.h> |
#include <base/args.h> |
#include <pal/dir.h> |
#include <base/dir.h> |
|
#include <base/log.h> | #include <base/log.h> |
#include <base/env.h> | #include <base/env.h> |
#include <base/process.h> | #include <base/process.h> |
|
|
#include <base/paths.h> | #include <base/paths.h> |
#include <base/conf.h> | #include <base/conf.h> |
#include <base/user.h> | #include <base/user.h> |
#include <base/getopt.h> |
#include <base/omigetopt.h> |
|
#include <base/multiplex.h> |
|
#include <base/Strand.h> |
|
#include <pal/format.h> |
| |
#if defined(CONFIG_POSIX) | #if defined(CONFIG_POSIX) |
# include <signal.h> | # include <signal.h> |
# include <sys/wait.h> | # include <sys/wait.h> |
|
# include <pthread.h> |
#endif | #endif |
| |
#define T MI_T |
|
|
|
typedef struct _ServerData ServerData; | typedef struct _ServerData ServerData; |
| |
typedef enum _ServerTransportType | typedef enum _ServerTransportType |
|
|
struct _ServerData | struct _ServerData |
{ | { |
Disp disp; | Disp disp; |
Protocol* protocol; |
MuxIn mux; |
|
ProtocolBase* protocol; |
WSMAN* wsman; | WSMAN* wsman; |
Selector selector; | Selector selector; |
MI_Boolean selectorInitialized; | MI_Boolean selectorInitialized; |
|
|
typedef struct _Options | typedef struct _Options |
{ | { |
MI_Boolean help; | MI_Boolean help; |
|
#if !defined(CONFIG_FAVORSIZE) |
MI_Boolean trace; | MI_Boolean trace; |
|
#endif |
MI_Boolean httptrace; | MI_Boolean httptrace; |
MI_Boolean terminateByNoop; | MI_Boolean terminateByNoop; |
#if defined(CONFIG_POSIX) | #if defined(CONFIG_POSIX) |
|
|
MI_Boolean logstderr; | MI_Boolean logstderr; |
unsigned short httpport; | unsigned short httpport; |
unsigned short httpsport; | unsigned short httpsport; |
|
char* sslCipherSuite; |
|
Server_SSL_Options sslOptions; |
MI_Uint64 idletimeout; | MI_Uint64 idletimeout; |
MI_Uint64 livetime; | MI_Uint64 livetime; |
Log_Level logLevel; | Log_Level logLevel; |
|
|
| |
static const char* arg0 = 0; | static const char* arg0 = 0; |
| |
static const char HELP[] = "\ |
static const ZChar HELP[] = ZT("\ |
Usage: %s [OPTIONS]\n\ | Usage: %s [OPTIONS]\n\ |
\n\ | \n\ |
This program starts the server.\n\ | This program starts the server.\n\ |
|
|
-l, --logstderr Send log output to standard error.\n\ | -l, --logstderr Send log output to standard error.\n\ |
--loglevel LEVEL Set logging level to one of the following\n\ | --loglevel LEVEL Set logging level to one of the following\n\ |
symbols/numbers: fatal/0, error/1, warning/2,\n\ | symbols/numbers: fatal/0, error/1, warning/2,\n\ |
info/3, debug/4 (default 2).\n\ |
info/3, debug/4, verbose/5 (default 2).\n\ |
--httptrace Enable logging of HTTP traffic.\n\ | --httptrace Enable logging of HTTP traffic.\n\ |
\n"; |
--timestamp Print timestamp server was built with.\n\ |
|
\n"); |
|
|
|
STRAND_DEBUGNAME( NoopRequest ); |
| |
PRINTF_FORMAT(1, 2) |
static void FUNCTION_NEVER_RETURNS err(const ZChar* fmt, ...) |
void FUNCTION_NEVER_RETURNS err(const char* fmt, ...) |
|
{ | { |
va_list ap; | va_list ap; |
memset(&ap, 0, sizeof(ap)); | memset(&ap, 0, sizeof(ap)); |
| |
fprintf(stderr, "%s: ", arg0); |
Ftprintf(stderr, ZT("%s: "), scs(arg0)); |
| |
va_start(ap, fmt); | va_start(ap, fmt); |
vfprintf(stderr, fmt, ap); |
Vftprintf(stderr, fmt, ap); |
va_end(ap); | va_end(ap); |
| |
/* Write to log as well */ | /* Write to log as well */ |
va_start(ap, fmt); | va_start(ap, fmt); |
|
__LOGE((fmt, ap)); |
va_end(ap); | va_end(ap); |
| |
fputc('\n', stderr); |
Ftprintf(stderr, ZT("\n")); |
exit(1); | exit(1); |
} | } |
| |
static void _ProviderCallback(Message* msg, void* callbackData) |
static void FUNCTION_NEVER_RETURNS info_exit(const ZChar* fmt, ...) |
{ | { |
ServerCallbackData* self = (ServerCallbackData* )callbackData; |
va_list ap; |
|
memset(&ap, 0, sizeof(ap)); |
|
|
|
Ftprintf(stderr, ZT("%s: "), scs(arg0)); |
|
|
|
va_start(ap, fmt); |
|
Vftprintf(stderr, fmt, ap); |
|
va_end(ap); |
|
|
|
/* Write to log as well */ |
|
va_start(ap, fmt); |
|
__LOGI((fmt, ap)); |
|
va_end(ap); |
|
|
|
Ftprintf(stderr, ZT("\n")); |
|
exit(0); |
|
} |
| |
|
void PrintProviderMsg( _In_ Message* msg) |
|
{ |
|
#if !defined(CONFIG_FAVORSIZE) |
|
if (s_opts.trace) |
|
{ |
switch ( msg->tag ) | switch ( msg->tag ) |
{ | { |
case PostResultMsgTag: | case PostResultMsgTag: |
{ | { |
const PostResultMsg* rsp = (const PostResultMsg*)msg; | const PostResultMsg* rsp = (const PostResultMsg*)msg; |
|
|
if (s_opts.trace) |
|
{ |
|
PostResultMsg_Print(rsp, stdout); | PostResultMsg_Print(rsp, stdout); |
} | } |
} |
|
break; | break; |
| |
case PostInstanceMsgTag: | case PostInstanceMsgTag: |
{ | { |
const PostInstanceMsg* rsp = (const PostInstanceMsg*)msg; | const PostInstanceMsg* rsp = (const PostInstanceMsg*)msg; |
|
|
if (s_opts.trace) |
|
{ |
|
PostInstanceMsg_Print(rsp, stdout); | PostInstanceMsg_Print(rsp, stdout); |
} | } |
} |
|
break; | break; |
| |
case SubscribeResTag: |
case PostSchemaMsgTag: |
{ |
|
const SubscribeRes* rsp = (const SubscribeRes*)msg; |
|
|
|
if (s_opts.trace) |
|
{ | { |
SubscribeRes_Print(rsp, stdout); |
const PostSchemaMsg* rsp = (const PostSchemaMsg*)msg; |
} |
PostSchemaMsg_Print(rsp, stdout); |
} | } |
break; | break; |
| |
case NoOpRspTag: | case NoOpRspTag: |
break; /* send noop confirmation to the client */ |
break; // send noop confirmation to the client |
| |
default: | default: |
{ | { |
LOGF((T("unknown message type: %u"), msg->tag)); |
trace_UnknownMessageType(msg->tag); |
exit(1); | exit(1); |
} | } |
} | } |
|
|
/* forward message to the other side */ |
|
if (msg->request) |
|
msg->clientID = msg->request->clientID; |
|
|
|
switch (self->type) |
|
{ |
|
case SRV_PROTOCOL: |
|
Protocol_Send(self->data->protocol, msg); |
|
break; |
|
|
|
case SRV_WSMAN: |
|
WSMAN_Send(self->data->wsman, msg); |
|
break; |
|
|
|
default: |
|
LOGF((T("unknown transport type: %u"), (int)self->type)); |
|
exit(1); |
|
} | } |
|
#endif // !defined(CONFIG_FAVORSIZE) |
} | } |
| |
/* Called by protocol stack to dispatch an incoming request message */ |
/* |
static MI_Boolean _RequestCallback( |
Simple interaction object to respond to the noop request. |
Protocol* protocol_, |
It just sends a noop response and closes the interaction |
Message* msg, |
(therefore shutting down) |
void* data) |
*/ |
|
void _NoopInteractionAck( _In_ Strand* self) |
{ | { |
ServerCallbackData* self = (ServerCallbackData*)data; |
// do nothing |
MI_Result r; |
} |
| |
MI_UNUSED(protocol_); |
StrandFT _NoopInteractionUserFT = { |
|
NULL, |
|
NULL, |
|
_NoopInteractionAck, |
|
NULL, |
|
NULL, |
|
NULL, |
|
NULL, |
|
NULL, |
|
NULL, |
|
NULL, |
|
NULL, |
|
NULL }; |
| |
if (NoOpReqTag == msg->tag) |
static void _ProcessNoopRequest( |
|
_Inout_ InteractionOpenParams* params ) |
{ | { |
NoOpReq* req = (NoOpReq*)msg; |
Strand* strand; |
|
NoOpReq* req = (NoOpReq*)params->msg; |
NoOpRsp* rsp; | NoOpRsp* rsp; |
| |
|
#if !defined(CONFIG_FAVORSIZE) |
if (s_opts.trace) | if (s_opts.trace) |
{ | { |
NoOpReq_Print(req, stdout); | NoOpReq_Print(req, stdout); |
} | } |
|
#endif |
|
|
|
strand = Strand_New( STRAND_DEBUG( NoopRequest ) &_NoopInteractionUserFT, 0, STRAND_FLAG_ENTERSTRAND, params ); |
|
|
|
if( NULL == strand ) |
|
{ |
|
err(ZT("out of memory")); |
|
trace_OutOfMemory(); |
|
Strand_FailOpen(params); |
|
return; |
|
} |
| |
/* Send NoOp response back */ | /* Send NoOp response back */ |
rsp = NoOpRsp_New(req->base.msgID); |
rsp = NoOpRsp_New(req->base.base.operationId); |
| |
if (!rsp) | if (!rsp) |
err("out of memory"); |
{ |
|
err(ZT("out of memory")); |
rsp->base.clientID = req->base.clientID; |
trace_OutOfMemory(); |
|
Strand_FailOpen(params); |
|
return; |
|
} |
| |
|
#if !defined(CONFIG_FAVORSIZE) |
if (s_opts.trace) | if (s_opts.trace) |
{ | { |
NoOpRsp_Print(rsp, stdout); | NoOpRsp_Print(rsp, stdout); |
} | } |
|
#endif |
|
|
|
Strand_Ack( strand ); // Ack open msg |
|
Strand_Post( strand, &rsp->base ); |
|
Strand_Close( strand ); |
|
Strand_Leave( strand); |
| |
_ProviderCallback(&rsp->base, self); |
|
NoOpRsp_Release(rsp); | NoOpRsp_Release(rsp); |
| |
|
trace_ServerReceivedNoOpReqTag( (int)s_opts.terminateByNoop ); |
|
|
if (s_opts.terminateByNoop) | if (s_opts.terminateByNoop) |
{ | { |
s_data.terminated = MI_TRUE; | s_data.terminated = MI_TRUE; |
Selector_StopRunning(&s_data.selector); | Selector_StopRunning(&s_data.selector); |
} | } |
return MI_TRUE; |
|
} | } |
| |
if (s_opts.trace) |
/* Called by protocol stack to dispatch an incoming request message */ |
|
static void _RequestCallback( |
|
_Inout_ InteractionOpenParams* interactionParams ) |
{ | { |
MessagePrint(msg, stdout); |
ServerCallbackData* self = (ServerCallbackData*)interactionParams->callbackData; |
} |
Message* msg = interactionParams->msg; |
|
MI_Result result; |
msg->callback = _ProviderCallback; |
|
msg->callbackData = self; |
|
| |
r = Disp_HandleRequest(&self->data->disp, msg); |
DEBUG_ASSERT( NULL != interactionParams ); |
|
DEBUG_ASSERT( NULL != msg ); |
| |
if (MI_RESULT_OK != r) |
if (NoOpReqTag == msg->tag) |
{ | { |
PostResultMsg* resp; |
_ProcessNoopRequest( interactionParams ); |
|
return; |
resp = PostResultMsg_New( msg->msgID ); |
} |
|
|
if (!resp) |
|
return MI_TRUE; |
|
|
|
resp->result = r; |
|
Message_SetRequest(&resp->base,msg); |
|
(*msg->callback)(&resp->base, msg->callbackData); |
|
| |
PostResultMsg_Release(resp); |
#if 1 // !defined(CONFIG_FAVORSIZE) |
|
if (s_opts.trace) |
|
{ |
|
MessagePrint(msg, stdout); |
} | } |
|
#endif |
| |
return MI_TRUE; |
result = Disp_HandleInteractionRequest( |
|
&self->data->disp, |
|
interactionParams ); |
|
if( result != MI_RESULT_OK ) |
|
{ |
|
Strand_FailOpenWithResult(interactionParams, result, PostResultMsg_NewAndSerialize); |
|
} |
} | } |
| |
static void GetCommandLineDestDirOption( | static void GetCommandLineDestDirOption( |
|
|
if (strcmp(argv[i], "--destdir") == 0) | if (strcmp(argv[i], "--destdir") == 0) |
{ | { |
if (i + 1 == argc) | if (i + 1 == argc) |
err("missing argument for --destdir option"); |
err(ZT("missing argument for --destdir option")); |
| |
destdir = argv[i+1]; | destdir = argv[i+1]; |
memmove((char*)&argv[i], (char*)&argv[i+2], | memmove((char*)&argv[i], (char*)&argv[i+2], |
|
|
if (destdir) | if (destdir) |
{ | { |
if (SetPath(ID_DESTDIR, destdir) != 0) | if (SetPath(ID_DESTDIR, destdir) != 0) |
err("failed to set destdir"); |
err(ZT("failed to set destdir")); |
} | } |
| |
*argc_ = argc; | *argc_ = argc; |
|
|
"-p", | "-p", |
"-t", | "-t", |
"--httptrace", | "--httptrace", |
|
"--timestamp", |
"--stopnoop", | "--stopnoop", |
"-v", | "-v", |
"--version", | "--version", |
|
|
"--localstatedir:", | "--localstatedir:", |
"--sysconfdir:", | "--sysconfdir:", |
"--providerdir:", | "--providerdir:", |
|
"--registerdir:", |
"--certsdir:", | "--certsdir:", |
"--rundir:", | "--rundir:", |
"--logdir:", | "--logdir:", |
"--pidfile:", | "--pidfile:", |
"--logfile:", | "--logfile:", |
"--registerdir:", |
"--configfile:", |
"--socketfile:", | "--socketfile:", |
"--pemfile:", | "--pemfile:", |
"--keyfile:", | "--keyfile:", |
|
|
"--logstderr", | "--logstderr", |
"--loglevel:", | "--loglevel:", |
"-l", | "-l", |
|
"--testopts", |
NULL, | NULL, |
}; | }; |
| |
|
|
| |
if (r == -1) | if (r == -1) |
{ | { |
fprintf(stderr, "error: %s\n", state.err); |
Ftprintf(stderr, ZT("error: %s\n"), scs(state.err)); |
exit(1); | exit(1); |
} | } |
| |
|
|
{ | { |
s_opts.locations = MI_TRUE; | s_opts.locations = MI_TRUE; |
} | } |
|
#if !defined(CONFIG_FAVORSIZE) |
else if (strcmp(state.opt, "-t") == 0) | else if (strcmp(state.opt, "-t") == 0) |
{ | { |
s_opts.trace = MI_TRUE; | s_opts.trace = MI_TRUE; |
} | } |
|
#endif |
else if (strcmp(state.opt, "--httptrace") == 0) | else if (strcmp(state.opt, "--httptrace") == 0) |
{ | { |
s_opts.httptrace = MI_TRUE; | s_opts.httptrace = MI_TRUE; |
} | } |
|
else if (strcmp(state.opt, "--timestamp") == 0) |
|
{ |
|
#if defined(CONFIG_OS_WINDOWS) |
|
Tprintf(PAL_T("%s: %T\n"), scs(arg0), tcs(CONFIG_TIMESTAMP)); |
|
#else |
|
Tprintf(ZT("%s: %s\n"), scs(arg0), scs(CONFIG_TIMESTAMP)); |
|
#endif |
|
exit(0); |
|
} |
else if (strcmp(state.opt, "--stopnoop") == 0) | else if (strcmp(state.opt, "--stopnoop") == 0) |
{ | { |
s_opts.terminateByNoop = MI_TRUE; | s_opts.terminateByNoop = MI_TRUE; |
|
|
else if (strcmp(state.opt, "-v") == 0 || | else if (strcmp(state.opt, "-v") == 0 || |
strcmp(state.opt, "--version") == 0) | strcmp(state.opt, "--version") == 0) |
{ | { |
printf("%s: %s\n", arg0, |
#if defined(CONFIG_OS_WINDOWS) |
CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE); |
Tprintf(PAL_T("%s: %T\n"), scs(arg0), |
|
tcs(CONFIG_PRODUCT PAL_T("-") CONFIG_VERSION PAL_T(" - ") CONFIG_DATE)); |
|
#else |
|
Tprintf(ZT("%s: %s\n"), scs(arg0), |
|
scs(CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE)); |
|
#endif |
exit(0); | exit(0); |
} | } |
#if defined(CONFIG_POSIX) | #if defined(CONFIG_POSIX) |
|
|
else if (strcmp(state.opt, "--httpport") == 0) | else if (strcmp(state.opt, "--httpport") == 0) |
{ | { |
unsigned long x; | unsigned long x; |
char* end; |
char* end = 0; |
| |
x = Strtoul(state.arg, &end, 10); | x = Strtoul(state.arg, &end, 10); |
| |
if (*end != '\0' || x > USHRT_MAX) | if (*end != '\0' || x > USHRT_MAX) |
err("bad option argument for --httpport: %s", state.arg); |
{ |
|
err(ZT("bad option argument for --httpport: %s"), |
|
scs(state.arg)); |
|
} |
| |
s_opts.httpport = (unsigned short)x; | s_opts.httpport = (unsigned short)x; |
} | } |
|
|
x = Strtoul(state.arg, &end, 10); | x = Strtoul(state.arg, &end, 10); |
| |
if (*end != '\0' || x > USHRT_MAX) | if (*end != '\0' || x > USHRT_MAX) |
err("bad option argument for --httpsport: %s", state.arg); |
{ |
|
err(ZT("bad option argument for --httpsport: %s"), |
|
scs(state.arg)); |
|
} |
| |
s_opts.httpsport = (unsigned short)x; | s_opts.httpsport = (unsigned short)x; |
} | } |
|
|
MI_Uint64 x = Strtoull(state.arg, &end, 10); | MI_Uint64 x = Strtoull(state.arg, &end, 10); |
| |
if (*end != '\0') | if (*end != '\0') |
err("bad option argument for --idletimeout: %s", state.arg); |
{ |
|
err(ZT("bad option argument for --idletimeout: %s"), |
|
scs(state.arg)); |
|
} |
| |
s_opts.idletimeout = x; | s_opts.idletimeout = x; |
} | } |
|
|
MI_Uint64 x = Strtoull(state.arg, &end, 10); | MI_Uint64 x = Strtoull(state.arg, &end, 10); |
| |
if (*end != '\0') | if (*end != '\0') |
err("bad option argument for --livetime: %s", state.arg); |
{ |
|
err(ZT("bad option argument for --livetime: %s"), |
|
scs(state.arg)); |
|
} |
| |
s_opts.livetime = x; | s_opts.livetime = x; |
} | } |
|
|
{ | { |
if (Log_SetLevelFromString(state.arg) != 0) | if (Log_SetLevelFromString(state.arg) != 0) |
{ | { |
err("bad option argument for %s: %s", state.opt, state.arg); |
err(ZT("bad option argument for %s: %s"), |
|
scs(state.opt), scs(state.arg)); |
|
} |
|
} |
|
else if (strcmp(state.opt, "--testopts") == 0) |
|
{ |
|
s_opts.httptrace = MI_TRUE; |
|
|
|
if (Log_SetLevelFromString("DEBUG") != 0) |
|
{ |
|
err(ZT("bad argument for Log_SetLevelFromString()")); |
} | } |
} | } |
else if (strncmp(state.opt, "--", 2) == 0 && IsNickname(state.opt+2)) | else if (strncmp(state.opt, "--", 2) == 0 && IsNickname(state.opt+2)) |
{ | { |
if (SetPathFromNickname(state.opt+2, state.arg) != 0) | if (SetPathFromNickname(state.opt+2, state.arg) != 0) |
err("SetPathFromNickname() failed"); |
err(ZT("SetPathFromNickname() failed")); |
} | } |
} | } |
| |
|
|
if (s_opts.logstderr) | if (s_opts.logstderr) |
{ | { |
if (Log_OpenStdErr() != MI_RESULT_OK) | if (Log_OpenStdErr() != MI_RESULT_OK) |
err("failed to open log file to stderr"); |
err(ZT("failed to open log file to stderr")); |
} | } |
else | else |
{ | { |
MI_Char path[MAX_PATH_SIZE]; |
TChar path[PAL_MAX_PATH_SIZE]; |
ZStrlcpy(path, GetPath(ID_LOGFILE), MI_COUNT(path)); |
TcsStrlcpy(path, OMI_GetPath(ID_LOGFILE), MI_COUNT(path)); |
| |
/* Open the log file */ | /* Open the log file */ |
if (Log_Open(path) != MI_RESULT_OK) | if (Log_Open(path) != MI_RESULT_OK) |
err("failed to open log file: %s", path); |
err(PAL_T("failed to open log file: %T"), tcs(path)); |
} | } |
} | } |
| |
#if defined(CONFIG_POSIX) | #if defined(CONFIG_POSIX) |
|
|
static void _HandleSIGTERM(int sig) | static void _HandleSIGTERM(int sig) |
{ | { |
if (sig == SIGTERM && s_data.selectorInitialized) | if (sig == SIGTERM && s_data.selectorInitialized) |
{ | { |
|
const char* socketFile = OMI_GetPath(ID_SOCKETFILE); |
s_data.terminated = MI_TRUE; | s_data.terminated = MI_TRUE; |
Selector_StopRunning(&s_data.selector); | Selector_StopRunning(&s_data.selector); |
|
if (socketFile != NULL && *socketFile != '\0') |
|
unlink(socketFile); |
} | } |
} | } |
| |
|
|
} | } |
} | } |
| |
|
/* An array of PIDS that abnormally exited */ |
|
#define NPIDS 16 |
|
static pid_t _pids[NPIDS]; |
|
static volatile size_t _npids; |
|
|
static void _HandleSIGCHLD(int sig) | static void _HandleSIGCHLD(int sig) |
{ | { |
if (sig == SIGCHLD) | if (sig == SIGCHLD) |
{ | { |
|
for (;;) |
|
{ |
int status = 0; | int status = 0; |
wait(&status); |
pid_t pid = waitpid(-1, &status, WNOHANG); |
|
|
|
/* If abnormal exit, append to PIDs array */ |
|
if (pid > 0 && !WIFEXITED(status)) |
|
{ |
|
/* Save PID so error can be logged outside this function */ |
|
if (_npids < NPIDS) |
|
_pids[_npids++] = pid; |
} | } |
|
|
|
if (pid > 0 || (pid == -1 && errno == EINTR)) |
|
continue; |
|
|
|
break; |
} | } |
#endif |
} |
|
} |
|
|
|
#endif /* defined(CONFIG_POSIX) */ |
| |
static void _PrintPaths() | static void _PrintPaths() |
{ | { |
|
|
| |
static void GetConfigFileOptions() | static void GetConfigFileOptions() |
{ | { |
char path[MAX_PATH_SIZE]; |
char path[PAL_MAX_PATH_SIZE]; |
Conf* conf; | Conf* conf; |
| |
/* Form the configuration file path */ | /* Form the configuration file path */ |
Strlcpy(path, GetPath(ID_CONFIGFILE), sizeof(path)); |
Strlcpy(path, OMI_GetPath(ID_CONFIGFILE), sizeof(path)); |
| |
/* Open the configuration file */ | /* Open the configuration file */ |
conf = Conf_Open(path); | conf = Conf_Open(path); |
if (!conf) | if (!conf) |
err("failed to open configuration file: %s", path); |
err(ZT("failed to open configuration file: %s"), scs(path)); |
| |
/* For each key=value pair in configuration file */ | /* For each key=value pair in configuration file */ |
for (;;) | for (;;) |
|
|
int r = Conf_Read(conf, &key, &value); | int r = Conf_Read(conf, &key, &value); |
| |
if (r == -1) | if (r == -1) |
err("%s: %s\n", path, Conf_Error(conf)); |
err(ZT("%s: %s\n"), path, scs(Conf_Error(conf))); |
| |
if (r == 1) | if (r == 1) |
break; | break; |
|
|
| |
if (*end != '\0' || x > USHRT_MAX) | if (*end != '\0' || x > USHRT_MAX) |
{ | { |
err("%s(%u): invalid value for '%s': %s", path, |
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
Conf_Line(conf), key, value); |
Conf_Line(conf), scs(key), scs(value)); |
} | } |
| |
s_opts.httpport = (unsigned short)x; | s_opts.httpport = (unsigned short)x; |
|
|
| |
if (*end != '\0' || x > USHRT_MAX) | if (*end != '\0' || x > USHRT_MAX) |
{ | { |
err("%s(%u): invalid value for '%s': %s", path, |
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
Conf_Line(conf), key, value); |
Conf_Line(conf), scs(key), scs(value)); |
} | } |
| |
s_opts.httpsport = (unsigned short)x; | s_opts.httpsport = (unsigned short)x; |
|
|
| |
if (*end != '\0') | if (*end != '\0') |
{ | { |
err("%s(%u): invalid value for '%s': %s", path, |
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
Conf_Line(conf), key, value); |
Conf_Line(conf), scs(key), scs(value)); |
} | } |
| |
s_opts.idletimeout = x; | s_opts.idletimeout = x; |
|
|
| |
if (*end != '\0') | if (*end != '\0') |
{ | { |
err("%s(%u): invalid value for '%s': %s", path, |
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
Conf_Line(conf), key, value); |
Conf_Line(conf), scs(key), scs(value)); |
} | } |
| |
s_opts.livetime = x; | s_opts.livetime = x; |
|
|
{ | { |
if (Strcasecmp(value, "true") == 0) | if (Strcasecmp(value, "true") == 0) |
{ | { |
|
#if !defined(CONFIG_FAVORSIZE) |
s_opts.trace = MI_TRUE; | s_opts.trace = MI_TRUE; |
|
#endif |
} | } |
else if (Strcasecmp(value, "false") == 0) | else if (Strcasecmp(value, "false") == 0) |
{ | { |
|
#if !defined(CONFIG_FAVORSIZE) |
s_opts.trace = MI_FALSE; | s_opts.trace = MI_FALSE; |
|
#endif |
} | } |
else | else |
{ | { |
err("%s(%u): invalid value for '%s': %s", path, |
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
Conf_Line(conf), key, value); |
Conf_Line(conf), scs(key), scs(value)); |
} | } |
} | } |
else if (strcmp(key, "httptrace") == 0) | else if (strcmp(key, "httptrace") == 0) |
|
|
} | } |
else | else |
{ | { |
err("%s(%u): invalid value for '%s': %s", path, |
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
Conf_Line(conf), key, value); |
Conf_Line(conf), scs(key), scs(value)); |
|
} |
|
} |
|
else if (strcmp(key, "loglevel") == 0) |
|
{ |
|
if (Log_SetLevelFromString(value) != 0) |
|
{ |
|
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
|
Conf_Line(conf), scs(key), scs(value)); |
|
} |
|
} |
|
else if (strcmp(key, "sslciphersuite") == 0) |
|
{ |
|
size_t valueLength = strlen(value); |
|
s_opts.sslCipherSuite = PAL_Malloc(valueLength + 1); |
|
if (s_opts.sslCipherSuite == NULL) |
|
err(ZT("Out of memory")); |
|
Strlcpy(s_opts.sslCipherSuite, value, valueLength+1); |
|
s_opts.sslCipherSuite[valueLength] = '\0'; |
|
} |
|
else if (Strcasecmp(key, "NoSSLv2") == 0) |
|
{ |
|
if (Strcasecmp(value, "true") == 0) |
|
{ |
|
s_opts.sslOptions |= DISABLE_SSL_V2; |
|
} |
|
else if (Strcasecmp(value, "false") != 0) |
|
{ |
|
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
|
Conf_Line(conf), scs(key), scs(value)); |
|
} |
|
} |
|
else if (Strcasecmp(key, "NoSSLv3") == 0) |
|
{ |
|
if (Strcasecmp(value, "true") == 0) |
|
{ |
|
s_opts.sslOptions |= DISABLE_SSL_V3; |
|
} |
|
else if (Strcasecmp(value, "false") != 0) |
|
{ |
|
err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), |
|
Conf_Line(conf), scs(key), scs(value)); |
} | } |
} | } |
else if (IsNickname(key)) | else if (IsNickname(key)) |
{ | { |
if (SetPathFromNickname(key, value) != 0) | if (SetPathFromNickname(key, value) != 0) |
err("SetPathFromNickname() failed"); |
err(ZT("SetPathFromNickname() failed")); |
} | } |
else | else |
{ | { |
err("%s(%u): unknown key: %s", path, Conf_Line(conf), key); |
err(ZT("%s(%u): unknown key: %s"), scs(path), Conf_Line(conf), |
|
scs(key)); |
} | } |
} | } |
| |
|
|
/* Print help */ | /* Print help */ |
if (s_opts.help) | if (s_opts.help) |
{ | { |
fprintf(stderr, HELP, arg0); |
Ftprintf(stderr, HELP, scs(arg0)); |
exit(1); | exit(1); |
} | } |
| |
|
|
if (s_opts.locations) | if (s_opts.locations) |
{ | { |
_PrintPaths(); | _PrintPaths(); |
printf("\n"); |
Tprintf(ZT("\n")); |
exit(0); | exit(0); |
} | } |
| |
|
|
if (s_opts.stop || s_opts.reloadConfig) | if (s_opts.stop || s_opts.reloadConfig) |
{ | { |
if (PIDFile_IsRunning() != 0) | if (PIDFile_IsRunning() != 0) |
err("server is not running\n"); |
info_exit(ZT("server is not running\n")); |
| |
if (PIDFile_Signal(s_opts.stop ? SIGTERM : SIGHUP) != 0) | if (PIDFile_Signal(s_opts.stop ? SIGTERM : SIGHUP) != 0) |
err("failed to stop server\n"); |
err(ZT("failed to stop server\n")); |
| |
if (s_opts.stop) | if (s_opts.stop) |
printf("%s: stopped server\n", arg0); |
Tprintf(ZT("%s: stopped server\n"), scs(arg0)); |
else | else |
printf("%s: refreshed server\n", arg0); |
Tprintf(ZT("%s: refreshed server\n"), scs(arg0)); |
| |
exit(0); | exit(0); |
} | } |
|
|
#if defined(CONFIG_POSIX) | #if defined(CONFIG_POSIX) |
| |
if (PIDFile_IsRunning() == 0) | if (PIDFile_IsRunning() == 0) |
err("server is already running\n"); |
err(ZT("server is already running\n")); |
| |
/* Verify that server is started as root */ | /* Verify that server is started as root */ |
if (0 != IsRoot() && !s_opts.ignoreAuthentication) | if (0 != IsRoot() && !s_opts.ignoreAuthentication) |
{ | { |
err("expected to run as root"); |
err(ZT("expected to run as root")); |
} | } |
| |
/* ATTN: unit-test support; should be removed/ifdefed later */ | /* ATTN: unit-test support; should be removed/ifdefed later */ |
|
|
/* Watch for SIGTERM signals */ | /* Watch for SIGTERM signals */ |
if (0 != SetSignalHandler(SIGTERM, _HandleSIGTERM) || | if (0 != SetSignalHandler(SIGTERM, _HandleSIGTERM) || |
0 != SetSignalHandler(SIGHUP, _HandleSIGHUP)) | 0 != SetSignalHandler(SIGHUP, _HandleSIGHUP)) |
err("cannot set sighanlder, erron %d", errno); |
err(ZT("cannot set sighanlder, erron %d"), errno); |
| |
| |
/* Watch for SIGCHLD signals */ | /* Watch for SIGCHLD signals */ |
|
|
#endif | #endif |
| |
/* Change directory to 'rundir' */ | /* Change directory to 'rundir' */ |
if (Chdir(GetPath(ID_RUNDIR)) != 0) |
if (Chdir(OMI_GetPath(ID_RUNDIR)) != 0) |
err("failed to change directory to: %s", GetPath(ID_RUNDIR)); |
{ |
|
err(ZT("failed to change directory to: %s"), |
|
scs(OMI_GetPath(ID_RUNDIR))); |
|
} |
| |
#if defined(CONFIG_POSIX) | #if defined(CONFIG_POSIX) |
/* Daemonize */ | /* Daemonize */ |
if (s_opts.daemonize && Process_Daemonize() != 0) | if (s_opts.daemonize && Process_Daemonize() != 0) |
err("failed to daemonize server process"); |
err(ZT("failed to daemonize server process")); |
#endif | #endif |
| |
#if defined(CONFIG_POSIX) | #if defined(CONFIG_POSIX) |
|
|
/* Create PID file */ | /* Create PID file */ |
if ((pidfile = PIDFile_OpenWrite()) == -1) | if ((pidfile = PIDFile_OpenWrite()) == -1) |
{ | { |
LOGF(("failed to create PID file: %s", GetPath(ID_PIDFILE))); |
trace_CreatePIDFileFailed( scs(OMI_GetPath(ID_PIDFILE)) ); |
exit(1); | exit(1); |
} | } |
|
|
#endif | #endif |
| |
/* Initialize calback parameters */ | /* Initialize calback parameters */ |
|
|
Sock_Start(); | Sock_Start(); |
| |
if(Selector_Init(&s_data.selector) != MI_RESULT_OK) | if(Selector_Init(&s_data.selector) != MI_RESULT_OK) |
err("Selector_Init() failed"); |
err(ZT("Selector_Init() failed")); |
| |
s_data.selectorInitialized = MI_TRUE; | s_data.selectorInitialized = MI_TRUE; |
|
|
|
Timer_SetSelector(&s_data.selector); |
} | } |
| |
/* Create the dispatcher object. */ | /* Create the dispatcher object. */ |
|
|
| |
if (r != MI_RESULT_OK) | if (r != MI_RESULT_OK) |
{ | { |
LOGF((T("failed to initialize the dispatcher: %u"), r)); |
trace_DispatchInitFailed(r); |
err("failed to initialize the dispatcher: %u", r); |
err(ZT("failed to initialize the dispatcher: %u"), r); |
} | } |
} | } |
| |
|
|
s_data.disp.agentmgr.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000; | s_data.disp.agentmgr.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000; |
} | } |
| |
/* wsman server */ |
/* Set WSMAN options and create WSMAN server */ |
{ | { |
|
WSMAN_Options options = DEFAULT_WSMAN_OPTIONS; |
|
#if !defined(CONFIG_FAVORSIZE) |
|
options.enableTracing = s_opts.trace; |
|
#endif |
|
options.enableHTTPTracing = s_opts.httptrace; |
|
|
r = WSMAN_New_Listener( | r = WSMAN_New_Listener( |
&s_data.wsman, | &s_data.wsman, |
&s_data.selector, | &s_data.selector, |
s_opts.httpport, | s_opts.httpport, |
s_opts.httpsport, | s_opts.httpsport, |
(WSMANCallback)_RequestCallback, /* ATTN! address callback types! */ |
s_opts.sslCipherSuite, |
&s_data.wsmanData); |
s_opts.sslOptions, |
|
_RequestCallback, |
|
&s_data.wsmanData, |
|
&options); |
| |
if (r != MI_RESULT_OK) | if (r != MI_RESULT_OK) |
err("WSMAN_New_Listener() failed"); |
err(ZT("WSMAN_New_Listener() failed")); |
} | } |
| |
/* Set WSMAN options */ |
/* mux */ |
{ | { |
WSMAN_Options options = DEFAULT_WSMAN_OPTIONS; |
if(MuxIn_Init(&s_data.mux, _RequestCallback, &s_data.protocolData, NULL, PostResultMsg_NewAndSerialize) != MI_RESULT_OK) |
options.enableTracing = s_opts.trace; |
err(ZT("MuxIn_Init() failed")); |
options.enableHTTPTracing = s_opts.httptrace; |
|
WSMAN_SetOptions(s_data.wsman, &options); |
|
} | } |
| |
/* Create new protocol object */ | /* Create new protocol object */ |
{ | { |
r = Protocol_New_Listener(&s_data.protocol, &s_data.selector, |
r = ProtocolBase_New_Listener( |
GetPath(ID_SOCKETFILE), _RequestCallback, &s_data.protocolData); |
&s_data.protocol, |
|
&s_data.selector, |
|
OMI_GetPath(ID_SOCKETFILE), |
|
MuxIn_Open, |
|
&s_data.mux); |
| |
if (r != MI_RESULT_OK) | if (r != MI_RESULT_OK) |
err("Protocol_New_Listener() failed"); |
err(ZT("Protocol_New_Listener() failed")); |
} | } |
| |
/* Log start up message */ | /* Log start up message */ |
LOGI((T("listening on ports: http %u, https %u"), s_opts.httpport, s_opts.httpsport)); |
trace_ListeningOnPorts(s_opts.httpport, s_opts.httpsport); |
| |
/* Run the protocol object (waiting for new messages) */ | /* Run the protocol object (waiting for new messages) */ |
r = Protocol_Run(s_data.protocol, |
{ |
(s_opts.livetime ? s_opts.livetime * 1000000 : TIME_NEVER)); |
const PAL_Uint64 ONE_SECOND_USEC = 1000 * 1000; |
|
PAL_Uint64 start; |
|
PAL_Uint64 finish; |
|
|
|
PAL_Time(&start); |
|
|
|
if (s_opts.livetime) |
|
finish = start + (s_opts.livetime * ONE_SECOND_USEC); |
|
else |
|
finish = 0; |
|
|
|
for (;;) |
|
{ |
|
PAL_Uint64 now; |
|
|
|
r = Protocol_Run(s_data.protocol, ONE_SECOND_USEC); |
| |
LOGI((T("after run, r %d"), r)); |
if (r != MI_RESULT_TIME_OUT) |
|
break; |
|
|
|
PAL_Time(&now); |
|
|
|
/* Log abnormally terminated terminated process */ |
|
{ |
|
size_t i; |
|
|
|
for (i = 0; i < _npids; i++) |
|
trace_ChildProcessTerminatedAbnormally(_pids[i]); |
|
|
|
_npids = 0; |
|
} |
|
|
|
if (finish && now > finish) |
|
break; |
|
} |
|
} |
|
|
|
trace_Server_ProtocolRun(r); |
| |
s_data.selectorInitialized = MI_FALSE; | s_data.selectorInitialized = MI_FALSE; |
| |
if (MI_RESULT_TIME_OUT == r) | if (MI_RESULT_TIME_OUT == r) |
{ | { |
LOGI((T("livetime expired; server stopped"))); |
trace_Server_LiveTimeExpired(); |
s_data.terminated = MI_TRUE; | s_data.terminated = MI_TRUE; |
} | } |
| |
|
|
if (r == MI_RESULT_OK) | if (r == MI_RESULT_OK) |
{ | { |
if (s_data.terminated) | if (s_data.terminated) |
LOGI((T("server terminated"))); |
trace_ServerTerminated(); |
else | else |
LOGI((T("re-reading configuration"))); |
trace_ServerReReadingConfig(); |
} | } |
#endif | #endif |
| |
|
|
Selector_RemoveAllHandlers(&s_data.selector); | Selector_RemoveAllHandlers(&s_data.selector); |
Disp_Destroy(&s_data.disp); | Disp_Destroy(&s_data.disp); |
WSMAN_Delete(s_data.wsman); | WSMAN_Delete(s_data.wsman); |
Protocol_Delete(s_data.protocol); |
ProtocolBase_Delete(s_data.protocol); |
Selector_Destroy(&s_data.selector); | Selector_Destroy(&s_data.selector); |
| |
/* Shutdown the network */ | /* Shutdown the network */ |
|
|
| |
/* Remove PID file */ | /* Remove PID file */ |
if (PIDFile_Delete() != 0) | if (PIDFile_Delete() != 0) |
LOGW(("failed to remove PID file: %s", GetPath(ID_PIDFILE))); |
{ |
|
trace_FailedRemovePIDFile(scs(OMI_GetPath(ID_PIDFILE))); |
|
} |
#endif | #endif |
| |
/* Log that we are exiting */ | /* Log that we are exiting */ |
LOGI((T("server exiting"))); |
trace_ServerExiting(); |
| |
Log_Close(); | Log_Close(); |
|
|
|
#if defined(USE_ALLOCATOR) |
|
|
|
# if defined(USE_PAL_ATEXIT) |
|
PAL_AtexitCall(); |
|
# endif |
|
|
|
PAL_DumpAllocStats(); |
|
|
|
if (PAL_GetBlocksAllocated()) |
|
{ |
|
printf("WARNING: %s: server has unfreed blocks on exit\n", arg0); |
|
PAL_DumpAllocList(); |
|
} |
|
#endif |
|
|
return 0; | return 0; |
} | } |