(file) Return to server.c CVS log (file) (dir) Up to [OMI] / omi / server

   1 mike  1.1 /*
   2           **==============================================================================
   3           **
   4           ** Open Management Infrastructure (OMI)
   5           **
   6           ** Copyright (c) Microsoft Corporation
   7           ** 
   8           ** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
   9           ** use this file except in compliance with the License. You may obtain a copy 
  10           ** of the License at 
  11           **
  12           **     http://www.apache.org/licenses/LICENSE-2.0 
  13           **
  14           ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15           ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
  16           ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
  17           ** MERCHANTABLITY OR NON-INFRINGEMENT. 
  18           **
  19           ** See the Apache 2 License for the specific language governing permissions 
  20           ** and limitations under the License.
  21           **
  22 mike  1.1 **==============================================================================
  23           */
  24           
  25           #include <limits.h>
  26           #include <protocol/protocol.h>
  27 krisbash 1.4 #include <pal/sleep.h>
  28 mike     1.2 #include <wsman/wsman.h>
  29 mike     1.1 #include <provreg/provreg.h>
  30              #include <provmgr/provmgr.h>
  31              #include <disp/disp.h>
  32 krisbash 1.4 #include <pal/strings.h>
  33              #include <pal/dir.h>
  34 mike     1.1 #include <base/log.h>
  35              #include <base/env.h>
  36              #include <base/process.h>
  37              #include <base/pidfile.h>
  38              #include <base/paths.h>
  39              #include <base/conf.h>
  40              #include <base/user.h>
  41 krisbash 1.4 #include <base/omigetopt.h>
  42              #include <base/multiplex.h>
  43              #include <base/Strand.h>
  44              #include <pal/format.h>
  45 mike     1.1 
  46              #if defined(CONFIG_POSIX)
  47              # include <signal.h>
  48              # include <sys/wait.h>
  49 krisbash 1.4 # include <pthread.h>
  50 mike     1.1 #endif
  51              
  52              typedef struct _ServerData ServerData;
  53              
  54              typedef enum _ServerTransportType
  55              {
  56                  SRV_PROTOCOL,
  57                  SRV_WSMAN
  58              }
  59              ServerTransportType;
  60              
  61              typedef struct _ServerCallbackData
  62              {
  63                  ServerData*         data;
  64                  ServerTransportType type;
  65              }
  66              ServerCallbackData;
  67              
  68              struct _ServerData
  69              {
  70 krisbash 1.4     Disp            disp;
  71                  MuxIn           mux;
  72                  ProtocolBase*   protocol;
  73                  WSMAN*          wsman;
  74                  Selector        selector;
  75                  MI_Boolean      selectorInitialized;
  76                  MI_Boolean      terminated;
  77 mike     1.1 
  78                  /* pointers to self with different types - one per supported transport */
  79                  ServerCallbackData  protocolData;
  80                  ServerCallbackData  wsmanData;
  81              } ;
  82              
  83              typedef struct _Options
  84              {
  85                  MI_Boolean help;
  86 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
  87 mike     1.1     MI_Boolean trace;
  88 krisbash 1.4 #endif
  89 mike     1.2     MI_Boolean httptrace;
  90 mike     1.1     MI_Boolean terminateByNoop;
  91              #if defined(CONFIG_POSIX)
  92                  MI_Boolean daemonize;
  93                  MI_Boolean stop;
  94                  MI_Boolean reloadConfig;
  95              #endif
  96                  /* mostly for unittesting in non-root env */
  97                  MI_Boolean ignoreAuthentication;
  98                  MI_Boolean locations;
  99                  MI_Boolean logstderr;
 100                  unsigned short httpport;
 101                  unsigned short httpsport;
 102 krisbash 1.4     char* sslCipherSuite;
 103                  Server_SSL_Options sslOptions;
 104 mike     1.1     MI_Uint64 idletimeout;
 105                  MI_Uint64 livetime;
 106                  Log_Level logLevel;
 107              }
 108              Options;
 109              
 110              static Options s_opts;
 111              
 112              static ServerData s_data;
 113              
 114              static const char* arg0 = 0;
 115              
 116 krisbash 1.4 static const ZChar HELP[] = ZT("\
 117 mike     1.1 Usage: %s [OPTIONS]\n\
 118              \n\
 119              This program starts the server.\n\
 120              \n\
 121              OPTIONS:\n\
 122                  -h, --help                  Print this help message.\n\
 123                  -d                          Daemonize the server process (POSIX only).\n\
 124                  -s                          Stop the server process (POSIX only).\n\
 125                  -r                          Re-read configuration by the running server (POSIX only).\n\
 126                  --httpport PORT             HTTP protocol listener port.\n\
 127                  --httpsport PORT            HTTPS protocol listener port.\n\
 128                  --idletimeout TIMEOUT       Idle providers unload timeout (in seconds).\n\
 129                  -v, --version               Print version information.\n\
 130                  -l, --logstderr             Send log output to standard error.\n\
 131                  --loglevel LEVEL            Set logging level to one of the following\n\
 132                                              symbols/numbers: fatal/0, error/1, warning/2,\n\
 133 krisbash 1.4                                 info/3, debug/4, verbose/5 (default 2).\n\
 134 mike     1.2     --httptrace                 Enable logging of HTTP traffic.\n\
 135 krisbash 1.4     --timestamp                 Print timestamp server was built with.\n\
 136              \n");
 137              
 138              STRAND_DEBUGNAME( NoopRequest );
 139 mike     1.1 
 140 krisbash 1.4 static void FUNCTION_NEVER_RETURNS err(const ZChar* fmt, ...)
 141 mike     1.1 {
 142                  va_list ap;
 143                  memset(&ap, 0, sizeof(ap));
 144              
 145 krisbash 1.4     Ftprintf(stderr, ZT("%s: "), scs(arg0));
 146 mike     1.1 
 147                  va_start(ap, fmt);
 148 krisbash 1.4     Vftprintf(stderr, fmt, ap);
 149 mike     1.1     va_end(ap);
 150              
 151                  /* Write to log as well */
 152                  va_start(ap, fmt);
 153 krisbash 1.4     __LOGE((fmt, ap));
 154 mike     1.1     va_end(ap);
 155              
 156 krisbash 1.4     Ftprintf(stderr, ZT("\n"));
 157 mike     1.1     exit(1);
 158              }
 159              
 160 krisbash 1.4 static void FUNCTION_NEVER_RETURNS info_exit(const ZChar* fmt, ...)
 161 mike     1.1 {
 162 krisbash 1.4     va_list ap;
 163                  memset(&ap, 0, sizeof(ap));
 164              
 165                  Ftprintf(stderr, ZT("%s: "), scs(arg0));
 166              
 167                  va_start(ap, fmt);
 168                  Vftprintf(stderr, fmt, ap);
 169                  va_end(ap);
 170              
 171                  /* Write to log as well */
 172                  va_start(ap, fmt);
 173                  __LOGI((fmt, ap));
 174                  va_end(ap);
 175              
 176                  Ftprintf(stderr, ZT("\n"));
 177                  exit(0);
 178              }
 179 mike     1.1 
 180 krisbash 1.4 void PrintProviderMsg( _In_ Message* msg)
 181              {
 182              #if !defined(CONFIG_FAVORSIZE)
 183                  if (s_opts.trace)
 184 mike     1.1     {
 185 krisbash 1.4         switch ( msg->tag )
 186 mike     1.1         {
 187 krisbash 1.4             case PostResultMsgTag:
 188 mike     1.1             {
 189 krisbash 1.4                 const PostResultMsg* rsp = (const PostResultMsg*)msg;
 190 mike     1.1                 PostResultMsg_Print(rsp, stdout);
 191                          }
 192 krisbash 1.4             break;
 193 mike     1.1 
 194 krisbash 1.4             case PostInstanceMsgTag:
 195 mike     1.1             {
 196 krisbash 1.4                 const PostInstanceMsg* rsp = (const PostInstanceMsg*)msg;
 197 mike     1.1                 PostInstanceMsg_Print(rsp, stdout);
 198                          }
 199 krisbash 1.4             break;
 200 mike     1.1 
 201 krisbash 1.4             case PostSchemaMsgTag:
 202 mike     1.1             {
 203 krisbash 1.4                 const PostSchemaMsg* rsp = (const PostSchemaMsg*)msg;
 204                              PostSchemaMsg_Print(rsp, stdout);
 205 mike     1.1             }
 206 krisbash 1.4             break;
 207 mike     1.1 
 208 krisbash 1.4             case NoOpRspTag:
 209                              break;  // send noop confirmation to the client 
 210 mike     1.1 
 211 krisbash 1.4             default:
 212                          {
 213                              trace_UnknownMessageType(msg->tag);
 214                              exit(1);
 215                          }
 216 mike     1.1         }
 217                  }
 218 krisbash 1.4 #endif // !defined(CONFIG_FAVORSIZE)
 219              }
 220 mike     1.1 
 221 krisbash 1.4 /*
 222                  Simple interaction object to respond to the noop request.
 223                  It just sends a noop response and closes the interaction
 224                  (therefore shutting down)
 225              */
 226              void _NoopInteractionAck( _In_ Strand* self) 
 227              {
 228                  // do nothing
 229              }
 230 mike     1.1 
 231 krisbash 1.4 StrandFT _NoopInteractionUserFT = { 
 232                      NULL, 
 233                      NULL, 
 234                      _NoopInteractionAck, 
 235                      NULL, 
 236                      NULL, 
 237                      NULL,
 238                      NULL,
 239                      NULL, 
 240                      NULL, 
 241                      NULL, 
 242                      NULL, 
 243                      NULL };
 244 mike     1.1 
 245 krisbash 1.4 static void _ProcessNoopRequest(
 246                  _Inout_     InteractionOpenParams*  params )
 247 mike     1.1 {
 248 krisbash 1.4     Strand* strand;
 249                  NoOpReq* req = (NoOpReq*)params->msg;
 250                  NoOpRsp* rsp;
 251 mike     1.1 
 252 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
 253                  if (s_opts.trace)
 254                  {
 255                      NoOpReq_Print(req, stdout);
 256                  }
 257              #endif
 258                          
 259                  strand = Strand_New( STRAND_DEBUG( NoopRequest ) &_NoopInteractionUserFT, 0, STRAND_FLAG_ENTERSTRAND, params );
 260 mike     1.1 
 261 krisbash 1.4     if( NULL == strand )
 262 mike     1.1     {
 263 krisbash 1.4         err(ZT("out of memory"));
 264                      trace_OutOfMemory();
 265                      Strand_FailOpen(params);
 266                      return;
 267                  }
 268 mike     1.1 
 269 krisbash 1.4     /* Send NoOp response back */
 270                  rsp = NoOpRsp_New(req->base.base.operationId);
 271 mike     1.1 
 272 krisbash 1.4     if (!rsp)
 273                  {
 274                      err(ZT("out of memory"));
 275                      trace_OutOfMemory();
 276                      Strand_FailOpen(params);
 277                      return;
 278                  }
 279 mike     1.1 
 280 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
 281                  if (s_opts.trace)
 282                  {
 283                      NoOpRsp_Print(rsp, stdout);
 284                  }
 285              #endif
 286 mike     1.1 
 287 krisbash 1.4     Strand_Ack( strand );   // Ack open msg
 288                  Strand_Post( strand, &rsp->base );
 289                  Strand_Close( strand );   
 290                  Strand_Leave( strand);
 291                  
 292                  NoOpRsp_Release(rsp);
 293              
 294                  trace_ServerReceivedNoOpReqTag( (int)s_opts.terminateByNoop );
 295                  
 296                  if (s_opts.terminateByNoop)
 297                  {
 298                      s_data.terminated = MI_TRUE;
 299                      Selector_StopRunning(&s_data.selector);
 300                  }
 301              }
 302 mike     1.1 
 303 krisbash 1.4 /* Called by protocol stack to dispatch an incoming request message */
 304              static void _RequestCallback(
 305                  _Inout_ InteractionOpenParams* interactionParams )
 306              {
 307                  ServerCallbackData* self = (ServerCallbackData*)interactionParams->callbackData;
 308                  Message* msg = interactionParams->msg;
 309                  MI_Result result;
 310              
 311                  DEBUG_ASSERT( NULL != interactionParams );
 312                  DEBUG_ASSERT( NULL != msg );
 313                  
 314                  if (NoOpReqTag == msg->tag)
 315                  {
 316                      _ProcessNoopRequest( interactionParams );
 317                      return;
 318 mike     1.1     }
 319              
 320 krisbash 1.4 #if 1 // !defined(CONFIG_FAVORSIZE)
 321 mike     1.1     if (s_opts.trace)
 322                  {
 323                      MessagePrint(msg, stdout);
 324                  }
 325 krisbash 1.4 #endif
 326 mike     1.1 
 327 krisbash 1.4     result = Disp_HandleInteractionRequest(
 328                              &self->data->disp, 
 329                              interactionParams );
 330                  if( result != MI_RESULT_OK )
 331 mike     1.1     {
 332 krisbash 1.4         Strand_FailOpenWithResult(interactionParams, result, PostResultMsg_NewAndSerialize);
 333 mike     1.1     }
 334              }
 335 krisbash 1.4  
 336 mike     1.1 static void GetCommandLineDestDirOption(
 337                  int* argc_,
 338                  const char* argv[])
 339              {
 340                  int argc = *argc_;
 341                  int i;
 342                  const char* destdir = NULL;
 343              
 344                  for (i = 1; i < argc; )
 345                  {
 346                      if (strcmp(argv[i], "--destdir") == 0)
 347                      {
 348                          if (i + 1 == argc)
 349 krisbash 1.4                 err(ZT("missing argument for --destdir option"));
 350 mike     1.1 
 351                          destdir = argv[i+1];
 352                          memmove((char*)&argv[i], (char*)&argv[i+2], 
 353                              sizeof(char*) * (argc-i-1));
 354                          argc -= 2;
 355                      }
 356                      else if (strncmp(argv[i], "--destdir=", 10) == 0)
 357                      {
 358                          destdir = argv[i] + 10;
 359                          memmove((char*)&argv[i], (char*)&argv[i+1], 
 360                              sizeof(char*) * (argc-i));
 361              
 362                          argc -= 1;
 363                      }
 364                      else
 365                          i++;
 366                  }
 367              
 368                  if (destdir)
 369                  {
 370                      if (SetPath(ID_DESTDIR, destdir) != 0)
 371 krisbash 1.4             err(ZT("failed to set destdir"));
 372 mike     1.1     }
 373              
 374                  *argc_ = argc;
 375              }
 376              
 377              static void GetCommandLineOptions(
 378                  int* argc_,
 379                  const char* argv[])
 380              {
 381                  int argc = *argc_;
 382                  GetOptState state = GETOPTSTATE_INITIALIZER;
 383                  static const char* opts[] =
 384                  {
 385                      "-h",
 386                      "--help",
 387                      "-p",
 388                      "-t",
 389 mike     1.2         "--httptrace",
 390 krisbash 1.4         "--timestamp",
 391 mike     1.1         "--stopnoop",
 392                      "-v",
 393                      "--version",
 394                      "-d",
 395                      "-s",
 396                      "-r",
 397                      "--httpport:",
 398                      "--httpsport:",
 399                      "--idletimeout:",
 400                      "--livetime:",
 401                      "--ignoreAuthentication",
 402                      "-i",
 403                      "--prefix:",
 404                      "--libdir:",
 405                      "--bindir:",
 406                      "--localstatedir:",
 407                      "--sysconfdir:",
 408                      "--providerdir:",
 409 krisbash 1.4                 "--registerdir:",
 410 mike     1.1         "--certsdir:",
 411                      "--rundir:",
 412                      "--logdir:",
 413                      "--pidfile:",
 414                      "--logfile:",
 415 krisbash 1.4         "--configfile:",
 416 mike     1.1         "--socketfile:",
 417                      "--pemfile:",
 418                      "--keyfile:",
 419                      "--agentprogram:",
 420                      "--serverprogram:",
 421                      "--logstderr",
 422                      "--loglevel:",
 423                      "-l",
 424 krisbash 1.4         "--testopts",
 425 mike     1.1         NULL,
 426                  };
 427              
 428                  for (;;)
 429                  {
 430                      int r = GetOpt(&argc, argv, opts, &state);
 431              
 432                      if (r == 1)
 433                          break;
 434              
 435                      if (r == -1)
 436                      {
 437 krisbash 1.4             Ftprintf(stderr, ZT("error: %s\n"), scs(state.err));
 438 mike     1.1             exit(1);
 439                      }
 440              
 441                      if (strcmp(state.opt, "-h") == 0 ||
 442                          strcmp(state.opt, "--help") == 0)
 443                      {
 444                          s_opts.help = MI_TRUE;
 445                      }
 446                      else if (strcmp(state.opt, "-p") == 0)
 447                      {
 448                          s_opts.locations = MI_TRUE;
 449                      }
 450 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
 451 mike     1.1         else if (strcmp(state.opt, "-t") == 0)
 452                      {
 453                          s_opts.trace = MI_TRUE;
 454                      }
 455 krisbash 1.4 #endif
 456 mike     1.2         else if (strcmp(state.opt, "--httptrace") == 0)
 457                      {
 458                          s_opts.httptrace = MI_TRUE;
 459                      }
 460 krisbash 1.4         else if (strcmp(state.opt, "--timestamp") == 0)
 461                      {
 462              #if defined(CONFIG_OS_WINDOWS)
 463                          Tprintf(PAL_T("%s: %T\n"), scs(arg0), tcs(CONFIG_TIMESTAMP));
 464              #else
 465                          Tprintf(ZT("%s: %s\n"), scs(arg0), scs(CONFIG_TIMESTAMP));
 466              #endif
 467                          exit(0);
 468                      }
 469 mike     1.1         else if (strcmp(state.opt, "--stopnoop") == 0)
 470                      {
 471                          s_opts.terminateByNoop = MI_TRUE;
 472                      }
 473                      else if (strcmp(state.opt, "-v") == 0 ||
 474                              strcmp(state.opt, "--version") == 0)
 475                      {
 476 krisbash 1.4 #if defined(CONFIG_OS_WINDOWS)
 477                          Tprintf(PAL_T("%s: %T\n"), scs(arg0),
 478                              tcs(CONFIG_PRODUCT PAL_T("-") CONFIG_VERSION PAL_T(" - ") CONFIG_DATE));
 479              #else
 480                          Tprintf(ZT("%s: %s\n"), scs(arg0),
 481                              scs(CONFIG_PRODUCT "-" CONFIG_VERSION " - " CONFIG_DATE));
 482              #endif
 483 mike     1.1             exit(0);
 484                      }
 485              #if defined(CONFIG_POSIX)
 486                      else if (strcmp(state.opt, "-d") == 0)
 487                      {
 488                          s_opts.daemonize = MI_TRUE;
 489                      }
 490                      else if (strcmp(state.opt, "-s") == 0)
 491                      {
 492                          s_opts.stop = MI_TRUE;
 493                      }
 494                      else if (strcmp(state.opt, "-r") == 0)
 495                      {
 496                          s_opts.reloadConfig = MI_TRUE;
 497                      }
 498              #endif
 499                      else if (strcmp(state.opt, "--httpport") == 0)
 500                      {
 501                          unsigned long x;
 502 krisbash 1.4             char* end = 0;
 503 mike     1.1 
 504                          x = Strtoul(state.arg, &end, 10);
 505              
 506                          if (*end != '\0' || x > USHRT_MAX)
 507 krisbash 1.4             {
 508                              err(ZT("bad option argument for --httpport: %s"), 
 509                                  scs(state.arg));
 510                          }
 511 mike     1.1 
 512                          s_opts.httpport = (unsigned short)x;
 513                      }
 514                      else if (strcmp(state.opt, "--httpsport") == 0)
 515                      {
 516                          unsigned long x;
 517                          char* end;
 518              
 519                          x = Strtoul(state.arg, &end, 10);
 520              
 521                          if (*end != '\0' || x > USHRT_MAX)
 522 krisbash 1.4             {
 523                              err(ZT("bad option argument for --httpsport: %s"), 
 524                                  scs(state.arg));
 525                          }
 526 mike     1.1 
 527                          s_opts.httpsport = (unsigned short)x;
 528                      }
 529                      else if (strcmp(state.opt, "--idletimeout") == 0)
 530                      {
 531                          char* end;
 532                          MI_Uint64 x = Strtoull(state.arg, &end, 10);
 533              
 534                          if (*end != '\0')
 535 krisbash 1.4             {
 536                              err(ZT("bad option argument for --idletimeout: %s"), 
 537                                  scs(state.arg));
 538                          }
 539 mike     1.1 
 540                          s_opts.idletimeout = x;
 541                      }
 542                      else if (strcmp(state.opt, "--livetime") == 0)
 543                      {
 544                          char* end;
 545                          MI_Uint64 x = Strtoull(state.arg, &end, 10);
 546              
 547                          if (*end != '\0')
 548 krisbash 1.4             {
 549                              err(ZT("bad option argument for --livetime: %s"), 
 550                                  scs(state.arg));
 551                          }
 552 mike     1.1 
 553                          s_opts.livetime = x;
 554                      }
 555                      else if (strcmp(state.opt, "--ignoreAuthentication") == 0 ||
 556                           strcmp(state.opt, "-i") == 0)
 557                      {
 558                          s_opts.ignoreAuthentication = MI_TRUE;
 559                      }
 560                      else if (strcmp(state.opt, "--logstderr") == 0 ||
 561                           strcmp(state.opt, "-l") == 0)
 562                      {
 563                          s_opts.logstderr = MI_TRUE;
 564                      }
 565                      else if (strcmp(state.opt, "--loglevel") == 0)
 566                      {
 567                          if (Log_SetLevelFromString(state.arg) != 0)
 568                          {
 569 krisbash 1.4                 err(ZT("bad option argument for %s: %s"), 
 570                                  scs(state.opt), scs(state.arg));
 571                          }
 572                      }
 573                      else if (strcmp(state.opt, "--testopts") == 0)
 574                      {
 575                          s_opts.httptrace = MI_TRUE;
 576              
 577                          if (Log_SetLevelFromString("DEBUG") != 0)
 578                          {
 579                              err(ZT("bad argument for Log_SetLevelFromString()"));
 580 mike     1.1             }
 581                      }
 582                      else if (strncmp(state.opt, "--", 2) == 0 && IsNickname(state.opt+2))
 583                      {
 584                          if (SetPathFromNickname(state.opt+2, state.arg) != 0)
 585 krisbash 1.4                 err(ZT("SetPathFromNickname() failed"));
 586 mike     1.1         }
 587                  }
 588              
 589                  *argc_ = argc;
 590              }
 591              
 592              static void OpenLogFile()
 593              {
 594                  if (s_opts.logstderr)
 595                  {
 596                      if (Log_OpenStdErr() != MI_RESULT_OK)
 597 krisbash 1.4             err(ZT("failed to open log file to stderr"));
 598 mike     1.1     }
 599                  else
 600                  {
 601 krisbash 1.4         TChar path[PAL_MAX_PATH_SIZE];
 602                      TcsStrlcpy(path, OMI_GetPath(ID_LOGFILE), MI_COUNT(path));
 603 mike     1.1 
 604                      /* Open the log file */
 605                      if (Log_Open(path) != MI_RESULT_OK)
 606 krisbash 1.4             err(PAL_T("failed to open log file: %T"), tcs(path));
 607 mike     1.1     }
 608              }
 609              
 610              #if defined(CONFIG_POSIX)
 611 krisbash 1.4 
 612 mike     1.1 static void _HandleSIGTERM(int sig)
 613              {
 614                  if (sig == SIGTERM && s_data.selectorInitialized)
 615                  {
 616 krisbash 1.4         const char* socketFile = OMI_GetPath(ID_SOCKETFILE);
 617 mike     1.1         s_data.terminated = MI_TRUE;
 618                      Selector_StopRunning(&s_data.selector);
 619 krisbash 1.4         if (socketFile != NULL && *socketFile != '\0')
 620                          unlink(socketFile);
 621 mike     1.1     }
 622              }
 623              
 624              static void _HandleSIGHUP(int sig)
 625              {
 626                  if (sig == SIGHUP && s_data.selectorInitialized)
 627                  {
 628                      Selector_StopRunning(&s_data.selector);
 629                  }
 630              }
 631              
 632 krisbash 1.4 /* An array of PIDS that abnormally exited */
 633              #define NPIDS 16
 634              static pid_t _pids[NPIDS];
 635              static volatile size_t _npids;
 636              
 637 mike     1.1 static void _HandleSIGCHLD(int sig)
 638              {
 639                  if (sig == SIGCHLD)
 640                  {
 641 krisbash 1.4         for (;;)
 642                      {
 643                          int status = 0;
 644                          pid_t pid = waitpid(-1, &status, WNOHANG);
 645              
 646                          /* If abnormal exit, append to PIDs array */
 647                          if (pid > 0 && !WIFEXITED(status))
 648                          {
 649                              /* Save PID so error can be logged outside this function */
 650                              if (_npids < NPIDS)
 651                                  _pids[_npids++] = pid;
 652                          }
 653              
 654                          if (pid > 0 || (pid == -1 && errno == EINTR))
 655                              continue;
 656              
 657                          break;
 658                      }
 659 mike     1.1     }
 660              }
 661 krisbash 1.4 
 662              #endif /* defined(CONFIG_POSIX) */
 663 mike     1.1 
 664              static void _PrintPaths()
 665              {
 666                  PrintPaths();
 667              }
 668              
 669              static void GetConfigFileOptions()
 670              {
 671 krisbash 1.4     char path[PAL_MAX_PATH_SIZE];
 672 mike     1.1     Conf* conf;
 673              
 674                  /* Form the configuration file path */
 675 krisbash 1.4     Strlcpy(path, OMI_GetPath(ID_CONFIGFILE), sizeof(path));
 676 mike     1.1 
 677                  /* Open the configuration file */
 678                  conf = Conf_Open(path);
 679                  if (!conf)
 680 krisbash 1.4         err(ZT("failed to open configuration file: %s"), scs(path));
 681 mike     1.1 
 682                  /* For each key=value pair in configuration file */
 683                  for (;;)
 684                  {
 685                      const char* key;
 686                      const char* value;
 687                      int r = Conf_Read(conf, &key, &value);
 688              
 689                      if (r == -1)
 690 krisbash 1.4             err(ZT("%s: %s\n"), path, scs(Conf_Error(conf)));
 691 mike     1.1 
 692                      if (r == 1)
 693                          break;
 694              
 695                      if (strcmp(key, "httpport") == 0)
 696                      {
 697                          char* end;
 698                          unsigned long x = Strtoul(value, &end, 10);
 699              
 700                          if (*end != '\0' || x > USHRT_MAX)
 701                          {
 702 krisbash 1.4                 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), 
 703                                  Conf_Line(conf), scs(key), scs(value));
 704 mike     1.1             }
 705              
 706                          s_opts.httpport = (unsigned short)x;
 707                      }
 708                      else if (strcmp(key, "httpsport") == 0)
 709                      {
 710                          char* end;
 711                          unsigned long x = Strtoul(value, &end, 10);
 712              
 713                          if (*end != '\0' || x > USHRT_MAX)
 714                          {
 715 krisbash 1.4                 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), 
 716                                  Conf_Line(conf), scs(key), scs(value));
 717 mike     1.1             }
 718              
 719                          s_opts.httpsport = (unsigned short)x;
 720                      }
 721                      else if (strcmp(key, "idletimeout") == 0)
 722                      {
 723                          char* end;
 724                          MI_Uint64 x = Strtoull(value, &end, 10);
 725              
 726                          if (*end != '\0')
 727                          {
 728 krisbash 1.4                 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), 
 729                                  Conf_Line(conf), scs(key), scs(value));
 730 mike     1.1             }
 731              
 732                          s_opts.idletimeout = x;
 733                      }
 734                      else if (strcmp(key, "livetime") == 0)
 735                      {
 736                          char* end;
 737                          MI_Uint64 x = Strtoull(value, &end, 10);
 738              
 739                          if (*end != '\0')
 740                          {
 741 krisbash 1.4                 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), 
 742                                  Conf_Line(conf), scs(key), scs(value));
 743 mike     1.1             }
 744              
 745                          s_opts.livetime = x;
 746                      }
 747                      else if (strcmp(key, "trace") == 0)
 748                      {
 749                          if (Strcasecmp(value, "true") == 0)
 750                          {
 751 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
 752 mike     1.1                 s_opts.trace = MI_TRUE;
 753 krisbash 1.4 #endif
 754 mike     1.1             }
 755                          else if (Strcasecmp(value, "false") == 0)
 756                          {
 757 krisbash 1.4 #if !defined(CONFIG_FAVORSIZE)
 758 mike     1.1                 s_opts.trace = MI_FALSE;
 759 krisbash 1.4 #endif
 760 mike     1.1             }
 761                          else
 762                          {
 763 krisbash 1.4                 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), 
 764                                  Conf_Line(conf), scs(key), scs(value));
 765 mike     1.1             }
 766                      }
 767 mike     1.2         else if (strcmp(key, "httptrace") == 0)
 768                      {
 769                          if (Strcasecmp(value, "true") == 0)
 770                          {
 771                              s_opts.httptrace = MI_TRUE;
 772                          }
 773                          else if (Strcasecmp(value, "false") == 0)
 774                          {
 775                              s_opts.httptrace = MI_FALSE;
 776                          }
 777                          else
 778                          {
 779 krisbash 1.4                 err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), 
 780                                  Conf_Line(conf), scs(key), scs(value));
 781                          }
 782                      }
 783                      else if (strcmp(key, "loglevel") == 0)
 784                      {
 785                          if (Log_SetLevelFromString(value) != 0)
 786                          {
 787                              err(ZT("%s(%u): invalid value for '%s': %s"), scs(path), 
 788                                  Conf_Line(conf), scs(key), scs(value));
 789                          }
 790                      }
 791                      else if (strcmp(key, "sslciphersuite") == 0)
 792                      {
 793                          size_t valueLength = strlen(value);
 794                          s_opts.sslCipherSuite = PAL_Malloc(valueLength + 1);
 795                          if (s_opts.sslCipherSuite == NULL)
 796                              err(ZT("Out of memory"));
 797                          Strlcpy(s_opts.sslCipherSuite, value, valueLength+1);
 798                          s_opts.sslCipherSuite[valueLength] = '\0';
 799                      }
 800 krisbash 1.4         else if (Strcasecmp(key, "NoSSLv2") == 0)
 801                      {
 802                          if (Strcasecmp(value, "true") == 0)
 803                          {
 804                              s_opts.sslOptions |= DISABLE_SSL_V2;
 805                          }
 806                          else if (Strcasecmp(value, "false") != 0)
 807                          {
 808                              err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
 809                                  Conf_Line(conf), scs(key), scs(value));
 810                          }
 811                      }
 812                      else if (Strcasecmp(key, "NoSSLv3") == 0)
 813                      {
 814                          if (Strcasecmp(value, "true") == 0)
 815                          {
 816                              s_opts.sslOptions |= DISABLE_SSL_V3;
 817                          }
 818                          else if (Strcasecmp(value, "false") != 0)
 819                          {
 820                              err(ZT("%s(%u): invalid value for '%s': %s"), scs(path),
 821 krisbash 1.4                     Conf_Line(conf), scs(key), scs(value));
 822 mike     1.2             }
 823                      }
 824 mike     1.1         else if (IsNickname(key))
 825                      {
 826                          if (SetPathFromNickname(key, value) != 0)
 827 krisbash 1.4                 err(ZT("SetPathFromNickname() failed"));
 828 mike     1.1         }
 829                      else
 830                      {
 831 krisbash 1.4             err(ZT("%s(%u): unknown key: %s"), scs(path), Conf_Line(conf), 
 832                              scs(key));
 833 mike     1.1         }
 834                  }
 835              
 836                  /* Close configuration file */
 837                  Conf_Close(conf);
 838              
 839                  return;
 840              }
 841              
 842              int servermain(int argc, const char* argv[])
 843              {
 844                  MI_Result r;
 845              #if defined(CONFIG_POSIX)
 846                  int pidfile = -1;
 847              #endif
 848              
 849                  arg0 = argv[0];
 850              
 851                  memset(&s_data, 0, sizeof(s_data));
 852              
 853                  /* Set default options */
 854 mike     1.1     s_opts.httpport = CONFIG_HTTPPORT;
 855                  s_opts.httpsport = CONFIG_HTTPSPORT;
 856                  s_opts.idletimeout = 0;
 857                  s_opts.livetime = 0;
 858              
 859                  /* Get --destdir command-line option */
 860                  GetCommandLineDestDirOption(&argc, argv);
 861              
 862                  /* Extract configuration file options */
 863                  GetConfigFileOptions();
 864              
 865                  /* Extract command-line options a second time (to override) */
 866                  GetCommandLineOptions(&argc, argv);
 867              
 868                  /* Open the log file */
 869                  OpenLogFile();
 870              
 871                  /* Print help */
 872                  if (s_opts.help)
 873                  {
 874 krisbash 1.4         Ftprintf(stderr, HELP, scs(arg0));
 875 mike     1.1         exit(1);
 876                  }
 877              
 878                  /* Print locations of files and directories */
 879                  if (s_opts.locations)
 880                  {
 881                      _PrintPaths();
 882 krisbash 1.4         Tprintf(ZT("\n"));
 883 mike     1.1         exit(0);
 884                  }
 885              
 886              #if defined(CONFIG_POSIX)
 887                  if (s_opts.stop || s_opts.reloadConfig)
 888                  {
 889                      if (PIDFile_IsRunning() != 0)
 890 krisbash 1.4             info_exit(ZT("server is not running\n"));
 891 mike     1.1 
 892                      if (PIDFile_Signal(s_opts.stop ? SIGTERM : SIGHUP) != 0)
 893 krisbash 1.4             err(ZT("failed to stop server\n"));
 894 mike     1.1 
 895                      if (s_opts.stop)
 896 krisbash 1.4             Tprintf(ZT("%s: stopped server\n"), scs(arg0));
 897 mike     1.1         else
 898 krisbash 1.4             Tprintf(ZT("%s: refreshed server\n"), scs(arg0));
 899 mike     1.1 
 900                      exit(0);
 901                  }
 902              #endif
 903              
 904              #if defined(CONFIG_POSIX)
 905              
 906                  if (PIDFile_IsRunning() == 0)
 907 krisbash 1.4         err(ZT("server is already running\n"));
 908 mike     1.1 
 909                  /* Verify that server is started as root */
 910                  if (0 != IsRoot() && !s_opts.ignoreAuthentication)
 911                  {
 912 krisbash 1.4         err(ZT("expected to run as root"));
 913 mike     1.1     }
 914              
 915                  /* ATTN: unit-test support; should be removed/ifdefed later */
 916                  if (s_opts.ignoreAuthentication)
 917                  {
 918                      IgnoreAuthCalls(1);
 919                  }
 920              
 921                  /* Watch for SIGTERM signals */
 922                  if (0 != SetSignalHandler(SIGTERM, _HandleSIGTERM) ||
 923                      0 != SetSignalHandler(SIGHUP, _HandleSIGHUP))
 924 krisbash 1.4         err(ZT("cannot set sighanlder, erron %d"), errno);
 925 mike     1.1 
 926              
 927                  /* Watch for SIGCHLD signals */
 928                  SetSignalHandler(SIGCHLD, _HandleSIGCHLD);
 929              
 930              #endif
 931              
 932                  /* Change directory to 'rundir' */
 933 krisbash 1.4     if (Chdir(OMI_GetPath(ID_RUNDIR)) != 0)
 934                  {
 935                      err(ZT("failed to change directory to: %s"), 
 936                          scs(OMI_GetPath(ID_RUNDIR)));
 937                  }
 938 mike     1.1 
 939              #if defined(CONFIG_POSIX)
 940                  /* Daemonize */
 941                  if (s_opts.daemonize && Process_Daemonize() != 0)
 942 krisbash 1.4         err(ZT("failed to daemonize server process"));
 943 mike     1.1 #endif
 944              
 945              #if defined(CONFIG_POSIX)
 946              
 947                  /* Create PID file */
 948                  if ((pidfile = PIDFile_OpenWrite()) == -1)
 949                  {
 950 krisbash 1.4         trace_CreatePIDFileFailed( scs(OMI_GetPath(ID_PIDFILE)) );
 951 mike     1.1         exit(1);
 952                  }
 953 krisbash 1.4 
 954 mike     1.1 #endif
 955              
 956                  /* Initialize calback parameters */
 957                  s_data.protocolData.data = &s_data;
 958                  s_data.protocolData.type = SRV_PROTOCOL;
 959                  s_data.wsmanData.data = &s_data;
 960                  s_data.wsmanData.type = SRV_WSMAN;
 961              
 962                  while (!s_data.terminated)
 963                  {
 964                      /* selector */
 965                      {
 966                          /* Initialize the network */
 967                          Sock_Start();
 968              
 969                          if(Selector_Init(&s_data.selector) != MI_RESULT_OK)
 970 krisbash 1.4                 err(ZT("Selector_Init() failed"));
 971 mike     1.1 
 972                          s_data.selectorInitialized = MI_TRUE;
 973 krisbash 1.4 
 974                          Timer_SetSelector(&s_data.selector);
 975 mike     1.1         }
 976              
 977                      /* Create the dispatcher object. */
 978                      {
 979                          r = Disp_Init(&s_data.disp, &s_data.selector);
 980              
 981                          if (r != MI_RESULT_OK)
 982                          {
 983 krisbash 1.4                 trace_DispatchInitFailed(r);
 984                              err(ZT("failed to initialize the dispatcher: %u"), r);
 985 mike     1.1             }
 986                      }
 987              
 988                      if (s_opts.idletimeout)
 989                      {
 990                          /* convert it to usec */
 991                          s_data.disp.agentmgr.provmgr.idleTimeoutUsec = s_opts.idletimeout * 1000000;
 992                      }
 993              
 994 krisbash 1.4         /* Set WSMAN options and create WSMAN server */
 995 mike     1.1         {
 996 krisbash 1.4             WSMAN_Options options = DEFAULT_WSMAN_OPTIONS;
 997              #if !defined(CONFIG_FAVORSIZE)
 998                          options.enableTracing = s_opts.trace;
 999              #endif
1000                          options.enableHTTPTracing = s_opts.httptrace;
1001              
1002 mike     1.1             r = WSMAN_New_Listener(
1003                              &s_data.wsman, 
1004                              &s_data.selector, 
1005                              s_opts.httpport, 
1006                              s_opts.httpsport,
1007 krisbash 1.4                 s_opts.sslCipherSuite,
1008                              s_opts.sslOptions,
1009                              _RequestCallback,
1010                              &s_data.wsmanData,
1011                              &options);
1012 mike     1.1 
1013                          if (r != MI_RESULT_OK)
1014 krisbash 1.4                 err(ZT("WSMAN_New_Listener() failed"));
1015 mike     1.1         }
1016              
1017 krisbash 1.4         /* mux */
1018 mike     1.1         {
1019 krisbash 1.4             if(MuxIn_Init(&s_data.mux, _RequestCallback, &s_data.protocolData, NULL, PostResultMsg_NewAndSerialize) != MI_RESULT_OK)
1020                              err(ZT("MuxIn_Init() failed"));
1021 mike     1.1         }
1022 krisbash 1.4         
1023 mike     1.1         /* Create new protocol object */
1024                      {
1025 krisbash 1.4             r = ProtocolBase_New_Listener(
1026                              &s_data.protocol, 
1027                              &s_data.selector, 
1028                              OMI_GetPath(ID_SOCKETFILE), 
1029                              MuxIn_Open,
1030                              &s_data.mux);
1031 mike     1.1 
1032                          if (r != MI_RESULT_OK)
1033 krisbash 1.4                 err(ZT("Protocol_New_Listener() failed"));
1034 mike     1.1         }
1035              
1036                      /* Log start up message */
1037 krisbash 1.4         trace_ListeningOnPorts(s_opts.httpport, s_opts.httpsport);
1038 mike     1.1 
1039                      /* Run the protocol object (waiting for new messages) */
1040 krisbash 1.4         {
1041                          const PAL_Uint64 ONE_SECOND_USEC = 1000 * 1000;
1042                          PAL_Uint64 start;
1043                          PAL_Uint64 finish;
1044 mike     1.1 
1045 krisbash 1.4             PAL_Time(&start);
1046              
1047                          if (s_opts.livetime)
1048                              finish = start + (s_opts.livetime * ONE_SECOND_USEC);
1049                          else
1050                              finish = 0;
1051              
1052                          for (;;)
1053                          {
1054                              PAL_Uint64 now;
1055              
1056                              r = Protocol_Run(s_data.protocol, ONE_SECOND_USEC);
1057              
1058                              if (r != MI_RESULT_TIME_OUT)
1059                                  break;
1060              
1061                              PAL_Time(&now);
1062              
1063                              /* Log abnormally terminated terminated process */
1064                              {
1065                                  size_t i;
1066 krisbash 1.4 
1067                                  for (i = 0; i < _npids; i++)
1068                                      trace_ChildProcessTerminatedAbnormally(_pids[i]);
1069              
1070                                  _npids = 0;
1071                              }
1072              
1073                              if (finish && now > finish)
1074                                  break;
1075                          }
1076                      }
1077              
1078                      trace_Server_ProtocolRun(r);
1079 mike     1.1 
1080                      s_data.selectorInitialized = MI_FALSE;
1081              
1082                      if (MI_RESULT_TIME_OUT == r)
1083                      {
1084 krisbash 1.4             trace_Server_LiveTimeExpired();
1085 mike     1.1             s_data.terminated = MI_TRUE;
1086                      }
1087              
1088              #if defined(CONFIG_POSIX)
1089                      if (r == MI_RESULT_OK)
1090                      {
1091                          if (s_data.terminated)
1092 krisbash 1.4                 trace_ServerTerminated();
1093 mike     1.1             else
1094 krisbash 1.4                 trace_ServerReReadingConfig();
1095 mike     1.1         }
1096              #endif
1097              
1098                      // Destroy the dispatcher.
1099                      Selector_RemoveAllHandlers(&s_data.selector);
1100                      Disp_Destroy(&s_data.disp);
1101                      WSMAN_Delete(s_data.wsman);
1102 krisbash 1.4         ProtocolBase_Delete(s_data.protocol);
1103 mike     1.1         Selector_Destroy(&s_data.selector);
1104              
1105                      /* Shutdown the network */
1106                      Sock_Stop();
1107                  }
1108              
1109              #if defined(CONFIG_POSIX)
1110                  /* Close PID file */
1111                  close(pidfile);
1112              
1113                  /* Remove PID file */
1114                  if (PIDFile_Delete() != 0)
1115 krisbash 1.4     {
1116                      trace_FailedRemovePIDFile(scs(OMI_GetPath(ID_PIDFILE)));
1117                  }
1118 mike     1.1 #endif
1119              
1120                  /* Log that we are exiting */
1121 krisbash 1.4     trace_ServerExiting();
1122 mike     1.1 
1123                  Log_Close();
1124 krisbash 1.4 
1125              #if defined(USE_ALLOCATOR)
1126              
1127              # if defined(USE_PAL_ATEXIT)
1128                  PAL_AtexitCall();
1129              # endif
1130              
1131                  PAL_DumpAllocStats();
1132              
1133                  if (PAL_GetBlocksAllocated())
1134                  {
1135                      printf("WARNING: %s: server has unfreed blocks on exit\n", arg0);
1136                      PAL_DumpAllocList();
1137                  }
1138              #endif
1139              
1140 mike     1.1     return 0;
1141              }

ViewCVS 0.9.2