コード例 #1
0
ファイル: wr_application.c プロジェクト: donnoman/webroar
/** Add newly created worker to application */
int wr_app_wrk_insert(wr_svr_t *server, wr_wkr_t *worker,const wr_ctl_msg_t *ctl_msg) {
  LOG_FUNCTION
  wr_app_t* app = server->apps;
  const char* app_name = ctl_msg->msg.wkr.app_name.str;
  
  if(strcmp(app_name, WR_STATIC_FILE_SERVER_NAME) == 0){
    app = server->static_app;
  }

  while(app) {
    LOG_DEBUG(DEBUG,"app->a_config->max_worker = %d, app->wkr_que->q_count =%d", app->conf->max_worker, WR_QUEUE_SIZE(app->wkr_que));
    LOG_DEBUG(DEBUG, "Application name = %s, Application->config->name =%s", app_name, app->conf->name.str );
    if(app->conf->max_worker > WR_QUEUE_SIZE(app->wkr_que)
        && strcmp(app_name, app->conf->name.str) == 0) {
      int i;
      for(i = 0; i < app->pending_wkr ; i++) {
        if(app->last_wkr_pid[i] == worker->pid)
          break;
      }

      if(i == app->pending_wkr) {
        scgi_body_add(worker->ctl->scgi, "Either worker add timeout or worker PID does not match.",
                              strlen("Either worker add timeout or worker PID does not match."));
        return -1;
      }

      for(; i < app->pending_wkr ; i++) {
        app->last_wkr_pid[i] = app->last_wkr_pid[i+1];
      }
      app->last_wkr_pid[i] = 0;
      app->pending_wkr --;


      worker->id = ++worker_count;
      worker->app = app;
      
      if(app->pending_wkr <= 0)
        ev_timer_stop(app->svr->ebb_svr.loop, &app->t_add_timeout);
      if(!(worker->state& WR_WKR_ACTIVE))
        worker->state += WR_WKR_ACTIVE;

      if(app->in_use == FALSE) {
        app->in_use = TRUE;
        if(app->ctl) {
          LOG_DEBUG(DEBUG,"Send OK status");
          scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "OK", strlen("OK"));
          wr_ctl_resp_write(app->ctl);
          app->ctl = NULL;
        }
      }
      return 0;
    }
    app = app->next;
  }
  LOG_ERROR(SEVERE, "Either queue is full or Baseuri is not matched");
  scgi_body_add(worker->ctl->scgi, "Either queue is full or Baseuri is not matched.",
                        strlen("Either queue is full or Baseuri is not matched."));
  return -1;
}
コード例 #2
0
ファイル: worker.c プロジェクト: dharmarth/webroar
int drop_privileges(wkr_t *w, scgi_t *scgi) {
  char *str;
  
  str = (char*) scgi_header_value_get(scgi, "USER");
  
  if(str && strlen(str) > 0) {
    struct passwd *user_info=NULL;
    user_info = getpwnam(str);
    // Check for user existence
    if(user_info) {
      w->tmp->uid = user_info->pw_uid; 
      w->tmp->gid = user_info->pw_gid;
    } else {
      scgi_body_add(w->ctl->scgi, "Application run_as_user is invalid. Application not started.", strlen("Application run_as_user is invalid. Application not started."));
      LOG_ERROR(SEVERE,"Application run_as_user is invalid. Application not started.");
      return FALSE;
    }
  } else {
    scgi_body_add(w->ctl->scgi, "Application run_as_user is missing. Application not started.", strlen("Application run_as_user is missing. Application not started."));
    LOG_ERROR(SEVERE,"Application run_as_user is missing. Application not started.");
    return FALSE;
  }
  
  change_log_file_owner(w->tmp->uid, w->tmp->gid);
  //setting read, effective, saved group and user id
  if(setgid(w->tmp->gid)!=0) {
    scgi_body_add(w->ctl->scgi, "setegid() failed", strlen("setegid() failed"));
    LOG_ERROR(SEVERE,"setegid() failed");
    return FALSE;
  }
  if(setuid(w->tmp->uid)!=0) {
    scgi_body_add(w->ctl->scgi, "seteuid() failed", strlen("seteuid() failed"));
    LOG_ERROR(SEVERE,"seteuid() failed");
    return FALSE;
  }
  
  LOG_DEBUG(DEBUG,"Passed userid=%d and groupid=%d",
            w->tmp->uid, w->tmp->gid);
  LOG_DEBUG(DEBUG,"effective userid=%d and groupid=%d",geteuid(),getegid());
#ifdef __linux__
  int rv = prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
  LOG_DEBUG(DEBUG,"prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) = %d", rv);
  if (rv < 0) {
    LOG_ERROR(SEVERE,"error setting prctl(PR_SET_DUMPABLE, 1, 0, 0, 0), errno = %d, desc = %s", errno, strerror(errno));
  }
#endif  
  return TRUE;
}
コード例 #3
0
ファイル: wr_application.c プロジェクト: donnoman/webroar
/** Allication add callback */
void wr_app_add_cb(wr_ctl_t *ctl, const wr_ctl_msg_t *ctl_msg) {
  LOG_FUNCTION

  wr_svr_t* server = ctl->svr;
  wr_app_conf_t* app_conf = NULL;
  wr_app_t* app = server->apps, *tmp_app = NULL;
    
  while(app) {
    if(strcmp(ctl_msg->msg.app.app_name.str, app->conf->name.str)==0)
      break;
    tmp_app = app;
    app = app->next;
  }
  ctl->svr->err_msg[0] = 0;
  if(app) {
    sprintf(ctl->svr->err_msg, "Appliation '%s' is already running.", ctl_msg->msg.app.app_name.str);
  }
  
  if(!app && ctl && ctl->svr && ctl->svr->conf) {
    app_conf = wr_conf_app_read(ctl->svr->conf,
                           ctl_msg->msg.app.app_name.str,
                           ctl->svr->err_msg);
    if(app_conf!=NULL) {
      if(wr_app_insert(ctl->svr, app_conf, ctl) >= 0)
        return;
    } else if(ctl->svr->err_msg[0] == 0) {
      sprintf(ctl->svr->err_msg, "Appliation '%s' is not found.", ctl_msg->msg.app.app_name.str);
    }
  }

  scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
  scgi_body_add(ctl->scgi, ctl->svr->err_msg, strlen(ctl->svr->err_msg));
  wr_ctl_resp_write(ctl);
}
コード例 #4
0
ファイル: worker.c プロジェクト: dharmarth/webroar
void load_application(wkr_t* w){
  LOG_FUNCTION
  
  w->ctl->scgi = scgi_new();
  if(w->ctl->scgi == NULL) {
    LOG_ERROR(SEVERE,"Cannot create SCGI Request");
    sigproc();
    return;
  }
  
  w->http = http_new(w);
  if(w->http == NULL) {
    scgi_body_add(w->ctl->scgi, "unable to load application.", strlen("unable to load application."));
    LOG_ERROR(SEVERE,"unable to load application.");
  }else if(worker_listen(w) < 0) {
    scgi_body_add(w->ctl->scgi, "Error Initializing Workers.", strlen("Error Initializing Workers."));
    LOG_ERROR(WARN,"Error Initializing Workers.");
  }else{
    worker_accept_requests(w);
    LOG_INFO("Worker ready for serving requests.");
    init_idle_watcher(w);
    
    LOG_INFO("Successfully loaded rack application=%s with environment=%s",
             w->tmp->path.str,   w->tmp->env.str);
  }  
  
  //loading adapter according to application type
  LOG_DEBUG(DEBUG,"webroar_root = %s", w->tmp->root_path.str);
  LOG_DEBUG(DEBUG,"path = %s, name = %s, type = %s, environment = %s, baseuri = %s, analytics = %c",
            w->tmp->path.str,  w->tmp->name.str, w->tmp->type.str,
            w->tmp->env.str, w->tmp->resolver.str, w->tmp->profiler);
  
  // Send error or ok acknowledgement message
  if(w->ctl->scgi->body_length > 0){
    // Send error response
    w->ctl->error = TRUE;
    get_worker_add_ctl_scgi(w, TRUE);
    ev_io_start(w->loop,&(w->ctl->w_write));
    ev_timer_again(w->loop, &w->ctl->t_ack);
  }else{
    // Send acknowledgement message
    get_worker_add_ctl_scgi(w, FALSE);
    ev_io_start(w->loop,&(w->ctl->w_write));        
  }
  wkr_tmp_free(&w->tmp);
}
コード例 #5
0
ファイル: wr_application.c プロジェクト: donnoman/webroar
/** Callback function to add worker timeout */
void wr_app_wrk_add_timeout_cb(struct ev_loop *loop, ev_timer *w, int revents) {
  LOG_FUNCTION
  wr_app_t* app = (wr_app_t*) w->data;
  char err_msg[512];
  int err_msg_len = 0;
  
  // Stop add timeout timer
  ev_timer_stop(loop, &app->t_add_timeout);

  // Decreament active worker count
  if(app->pending_wkr > 0) {
    // Kill worker
    int pid = wr_app_fetch_wkr_pid(app);
    LOG_INFO("wr_app_wrk_add_timeout_cb: killing worker, pid = %d", pid);
    if(pid > 0)
      kill(pid ,SIGKILL);
    LOG_DEBUG(DEBUG,"app->pending_wkr = %d", app->pending_wkr);
    app->pending_wkr --;
    if(app->pending_wkr > 0) {
      ev_timer_again(loop, &app->t_add_timeout);
    }

    // Update high load ratio
    app->high_ratio = TOTAL_WORKER_COUNT(app) * WR_MAX_REQ_RATIO;
  }

  //TODO: Check minimum no. of workers and, cretae worker if needed.
  // Also, do not OK if some worker were failed to connect.
  // For timebeing sending OK even if some worker failed to connect.
  if(app->in_use == FALSE && app->ctl && app->pending_wkr == 0) {
    LOG_DEBUG(DEBUG,"Some problem occurred while starting Application %s.", app->conf->name.str);
    scgi_header_add(app->ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
    err_msg_len = sprintf(err_msg,"The application could not be started due to an error. Please refer '/var/log/webroar/%s.log' and the application log file for details.", app->conf->name.str); 
    scgi_body_add(app->ctl->scgi, err_msg, err_msg_len);
    wr_ctl_resp_write(app->ctl);
    app->ctl = NULL;
  } else if(app->in_use == TRUE && TOTAL_WORKER_COUNT(app) < app->conf->min_worker) {
    wr_app_wkr_add(app);
  }
}
コード例 #6
0
ファイル: wr_controller.c プロジェクト: webroar/webroar
wr_ctl_msg_t* wr_ctl_msg_validate(scgi_t* request, wr_ctl_t* ctl) {
  LOG_FUNCTION
  wr_ctl_msg_t* ctl_msg = wr_malloc(wr_ctl_msg_t);
  char *val;
  char error[STR_SIZE64];

  ctl->type = WR_CTL_MSG_NONE;
  ctl->scgi = scgi_new();

  val = (char*) scgi_header_value_get(request,"COMPONENT");
  if(val == NULL) {
    memcpy(error,"COMPONENT missing.", strlen("COMPONENT missing.")+1);
    goto ctl_msg_err;
  }
  scgi_header_add(ctl->scgi, "COMPONENT", strlen("COMPONENT"), val, strlen(val));
  if(strcmp(val,"APPLICATION")==0) {
    val = (char*) scgi_header_value_get(request,"METHOD");
    if(val == NULL) {
      memcpy(error,"METHOD missing.", strlen("METHOD missing.")+1);
      goto ctl_msg_err;
    }

    scgi_header_add(ctl->scgi, "METHOD", strlen("METHOD"), val, strlen(val));
    
    ctl_msg->msg.app.app_name.str = (char*) scgi_header_value_get(request,"APP_NAME");
    if(ctl_msg->msg.app.app_name.str)
      ctl_msg->msg.app.app_name.len = strlen(ctl_msg->msg.app.app_name.str);
    if(ctl_msg->msg.app.app_name.str == NULL) {
      memcpy(error,"Application name is missing.", strlen("Application name is missing.")+1);
      goto ctl_msg_err;
    }

    // Application Add
    if(strcmp(val,"ADD")==0) {
      ctl->type = WR_CTL_MSG_APPLICATION_ADD;
    } else if(strcmp(val,"REMOVE")==0) {
      ctl->type = WR_CTL_MSG_APPLICATION_REMOVE;
    } else if(strcmp(val,"RELOAD")==0) {
      ctl->type = WR_CTL_MSG_APPLICATION_RELOAD;
    }else {
      memcpy(error, "Invalid METHOD.", strlen("Invalid METHOD.")+1);
      goto ctl_msg_err;
    }
  } else if(strcmp(val,"WORKER")==0) {
    val = (char*) scgi_header_value_get(request,"METHOD");
    if(val == NULL) {
      memcpy(error, "METHOD missing.", strlen("METHOD missing.")+1);
      goto ctl_msg_err;
    }

    if(strcmp(val,"ERROR")==0) {
      scgi_header_add(ctl->scgi, "METHOD", strlen("METHOD"), "ACK", strlen("ACK"));
    }else{
      scgi_header_add(ctl->scgi, "METHOD", strlen("METHOD"), val, strlen(val));
    }
    
    // Worker Add
    if(strcmp(val,"ADD")==0) {
      ctl->type = WR_CTL_MSG_WORKER_ADD;

      ctl_msg->msg.wkr.app_name.str  =   (char*) scgi_header_value_get(request,"APPLICATION");
      if(ctl_msg->msg.wkr.app_name.str)
        ctl_msg->msg.wkr.app_name.len = strlen(ctl_msg->msg.wkr.app_name.str);
      ctl_msg->msg.wkr.pid.str =   (char*) scgi_header_value_get(request,"PID");
      if(ctl_msg->msg.wkr.pid.str)
        ctl_msg->msg.wkr.pid.len = strlen(ctl_msg->msg.wkr.pid.str);
      ctl_msg->msg.wkr.port.str  =   (char*) scgi_header_value_get(request,"PORT");
      if(ctl_msg->msg.wkr.port.str)
        ctl_msg->msg.wkr.port.len = strlen(ctl_msg->msg.wkr.port.str);
      ctl_msg->msg.wkr.sock_path.str  =   (char*) scgi_header_value_get(request,"SOCK_PATH");
      if(ctl_msg->msg.wkr.sock_path.str)
        ctl_msg->msg.wkr.sock_path.len = strlen(ctl_msg->msg.wkr.sock_path.str);
      ctl_msg->msg.wkr.uds.str  =   (char*) scgi_header_value_get(request,"UDS");
      if(ctl_msg->msg.wkr.uds.str)
        ctl_msg->msg.wkr.uds.len = strlen(ctl_msg->msg.wkr.uds.str);

      if(ctl_msg->msg.wkr.app_name.str == NULL ||
          ctl_msg->msg.wkr.pid.str == NULL ||
          ctl_msg->msg.wkr.uds.str == NULL) {
        memcpy(error, "Missing some headers.", strlen("Missing some headers.")+1);
        goto ctl_msg_err;
      }

    } else if(strcmp(val,"REMOVE")==0) {
      ctl->type = WR_CTL_MSG_WORKER_REMOVE;
    } else if(strcmp(val,"PING") == 0) {
      ctl->type = WR_CTL_MSG_WORKER_PING;
    } else if(strcmp(val,"CONF_REQ") == 0){
      ctl->type = WR_CTL_MSG_WORKER_CONF_REQ;
      ctl_msg->msg.wkr.app_name.str  =   (char*) scgi_header_value_get(request,"APPLICATION");
      if(ctl_msg->msg.wkr.app_name.str)
        ctl_msg->msg.wkr.app_name.len = strlen(ctl_msg->msg.wkr.app_name.str);
    } else if(strcmp(val,"ERROR") == 0) {
      ctl->type = WR_CTL_MSG_WORKER_ADD_ERROR;
      ctl_msg->msg.wkr.app_name.str  =   (char*) scgi_header_value_get(request,"APPLICATION");
      if(ctl_msg->msg.wkr.app_name.str)
        ctl_msg->msg.wkr.app_name.len = strlen(ctl_msg->msg.wkr.app_name.str);
      ctl_msg->msg.wkr.pid.str =   (char*) scgi_header_value_get(request,"PID");
      if(ctl_msg->msg.wkr.pid.str)
        ctl_msg->msg.wkr.pid.len = strlen(ctl_msg->msg.wkr.pid.str);
      ctl_msg->msg.wkr.port.str  =   (char*) scgi_header_value_get(request,"PORT");
      if(ctl_msg->msg.wkr.port.str)
        ctl_msg->msg.wkr.port.len = strlen(ctl_msg->msg.wkr.port.str);
      ctl_msg->msg.wkr.sock_path.str  =   (char*) scgi_header_value_get(request,"SOCK_PATH");
      if(ctl_msg->msg.wkr.sock_path.str)
        ctl_msg->msg.wkr.sock_path.len = strlen(ctl_msg->msg.wkr.sock_path.str);
      ctl_msg->msg.wkr.uds.str  =   (char*) scgi_header_value_get(request,"UDS");
      if(ctl_msg->msg.wkr.uds.str)
        ctl_msg->msg.wkr.uds.len = strlen(ctl_msg->msg.wkr.uds.str);

      if(ctl_msg->msg.wkr.app_name.str == NULL ||
          ctl_msg->msg.wkr.pid.str == NULL ||
          ctl_msg->msg.wkr.uds.str == NULL) {
        memcpy(error, "Missing some headers.", strlen("Missing some headers.")+1);
        goto ctl_msg_err;
      }
    }else {
      memcpy(error,"Invalid METHOD.", strlen("Invalid METHOD.")+1);
      goto ctl_msg_err;
    }
  } else {
    memcpy(error,"Invalid COMPONENT.", strlen("Invalid COMPONENT.")+1);
    goto ctl_msg_err;
  }

  return ctl_msg;
ctl_msg_err:
  LOG_ERROR(WARN,"Error found in controller message");
  ctl->type = WR_CTL_MSG_TYPE_ERROR;
  scgi_body_add(ctl->scgi, error, strlen(error));
  scgi_header_add(ctl->scgi, "STATUS", strlen("STATUS"), "ERROR", strlen("ERROR"));
  return ctl_msg;
}