コード例 #1
0
void send_fd_timed_out(int sigcode) 
{
    char *errstr;

    errstr = newString(HUGE_STRING_LEN,STR_TMP);
    if(exit_callback) (*exit_callback)();
    if (sigcode != SIGPIPE) {
	sprintf(errstr,"HTTPd: send timed out for %s, URL: %s", 
		(gCurrentRequest->remote_name ? 
		  gCurrentRequest->remote_name : "remote host"),
		(gCurrentRequest->url ? gCurrentRequest->url : "-"));
    }
    else {
	sprintf(errstr,"HTTPd: send aborted for %s, URL: %s", 
		(gCurrentRequest->remote_name ? 
		  gCurrentRequest->remote_name : "remote host"),
		(gCurrentRequest->url ? gCurrentRequest->url : "-"));
    }
    log_error(errstr,gCurrentRequest->hostInfo->error_log);
    log_transaction(gCurrentRequest);
    alarm(0);
    signal(SIGALRM,SIG_IGN);
    signal(SIGPIPE,SIG_IGN);
    CloseAll();  /* close all spurious file descriptors */

    if (!standalone) {
   	fclose(stdin); 
    	fclose(stdout); 
	exit(0);
    } else {
#ifdef NO_SIGLONGJMP
      longjmp(jmpbuffer,1);
#else
      siglongjmp(jmpbuffer,1);
#endif /* NO_SIGLONGJMP */
    }
}
コード例 #2
0
ファイル: main.c プロジェクト: whitepages/siege
int 
main(int argc, char *argv[])
{
  int            x; 
  int            result;
  DATA           D    = new_data();
  ARRAY          urls = new_array();
  CREW           crew;  
  LINES          *lines;   
  CLIENT         *client; 
  pthread_t      cease; 
  pthread_t      timer;  
  pthread_attr_t scope_attr; 
  void *statusp;
  sigset_t sigs;

  sigemptyset(&sigs);
  sigaddset(&sigs, SIGHUP);
  sigaddset(&sigs, SIGINT);
  sigaddset(&sigs, SIGALRM);
  sigaddset(&sigs, SIGTERM);
  sigprocmask(SIG_BLOCK, &sigs, NULL);

  lines = xcalloc(1, sizeof *lines);
  lines->index   = 0;
  lines->line    = NULL;

  memset(&my, 0, sizeof(struct CONFIG));

  parse_rc_cmdline(argc, argv); 
  if (init_config() < 0) {      /* defined in init.h   */
    exit( EXIT_FAILURE );       /* polly was a girl... */
  } 
  parse_cmdline(argc, argv);    /* defined above       */
  ds_module_check();            /* check config integ  */

  /**
   * XXX: we should consider moving the following
   * if-checks into the ds_module_check
   */

  if (my.config) {
    show_config(TRUE);    
  }

  if (my.url != NULL) {
    my.length = 1; 
  } else { 
    my.length = read_cfg_file(lines, my.file); 
  }

  if (my.reps < 0) {
    my.reps = my.length;
  }

  if (my.length == 0) { 
    display_help();
  }

  /* cookie is an EXTERN, defined in setup */ 
  cookie = xcalloc(sizeof(COOKIE), 1); 
  cookie->first = NULL;
  if ((result = pthread_mutex_init( &(cookie->mutex), NULL)) !=0) {
    NOTIFY(FATAL, "pthread_mutex_init" );
  } 

  /* memory allocation for threads and clients */
  client = xcalloc(my.cusers, sizeof(CLIENT));
  if ((crew = new_crew(my.cusers, my.cusers, FALSE)) == NULL) {
    NOTIFY(FATAL, "unable to allocate memory for %d simulated browser", my.cusers);  
  }

  /** 
   * determine the source of the url(s),
   * command line or file, and add them
   * to the urls struct.
   */

  if (my.url != NULL) {
    URL tmp = new_url(my.url);
    url_set_ID(tmp, 0);
    if (my.get && url_get_method(tmp) != POST && url_get_method(tmp) != PUT) {
      url_set_method(tmp, my.method); 
    }
    array_npush(urls, tmp, URLSIZE); // from cmd line
  } else { 
    for (x = 0; x < my.length; x++) {
      URL tmp = new_url(lines->line[x]);
      url_set_ID(tmp, x);
      array_npush(urls, tmp, URLSIZE);
    }
  } 

  /**
   * display information about the siege
   * to the user and prepare for verbose 
   * output if necessary.
   */
  if (!my.get && !my.quiet) {
    fprintf(stderr, "** "); 
    display_version(FALSE);
    fprintf(stderr, "** Preparing %d concurrent users for battle.\n", my.cusers);
    fprintf(stderr, "The server is now under siege...");
    if (my.verbose) { fprintf(stderr, "\n"); }
  }

  /**
   * record start time before spawning threads
   * as the threads begin hitting the server as
   * soon as they are created.
   */
  data_set_start(D);

  /**
   * for each concurrent user, spawn a thread and
   * loop until condition or pthread_cancel from the
   * handler thread.
   */
  pthread_attr_init(&scope_attr);
  pthread_attr_setscope(&scope_attr, PTHREAD_SCOPE_SYSTEM);
#if defined(_AIX)
  /* AIX, for whatever reason, defies the pthreads standard and  *
   * creates threads detached by default. (see pthread.h on AIX) */
  pthread_attr_setdetachstate(&scope_attr, PTHREAD_CREATE_JOINABLE);
#endif

  /** 
   * invoke OpenSSL's thread safety
   */
#ifdef HAVE_SSL
  SSL_thread_setup();
#endif

  /**
   * create the signal handler and timer;  the
   * signal handler thread (cease) responds to
   * ctrl-C (sigterm) and the timer thread sends
   * sigterm to cease on time out.
   */
  if ((result = pthread_create(&cease, NULL, (void*)sig_handler, (void*)crew)) < 0) {
    NOTIFY(FATAL, "failed to create handler: %d\n", result);
  }
  if (my.secs > 0) {
    if ((result = pthread_create(&timer, NULL, (void*)siege_timer, (void*)cease)) < 0) {
      NOTIFY(FATAL, "failed to create handler: %d\n", result);
    } 
  }

  /**
   * loop until my.cusers and create a corresponding thread...
   */  
  for (x = 0; x < my.cusers && crew_get_shutdown(crew) != TRUE; x++) {
    client[x].id              = x; 
    client[x].bytes           = 0;
    client[x].time            = 0.0;
    client[x].hits            = 0;
    client[x].code            = 0;
    client[x].ok200           = 0;   
    client[x].fail            = 0; 
    client[x].urls            = urls;
    client[x].auth.www        = 0;
    client[x].auth.proxy      = 0;
    client[x].auth.type.www   = BASIC;
    client[x].auth.type.proxy = BASIC;
    client[x].rand_r_SEED     = urandom();
    result = crew_add(crew, (void*)start_routine, &(client[x]));
    if (result == FALSE) { 
      my.verbose = FALSE;
      fprintf(stderr, "Unable to spawn additional threads; you may need to\n");
      fprintf(stderr, "upgrade your libraries or tune your system in order\n"); 
      fprintf(stderr, "to exceed %d users.\n", my.cusers);
      NOTIFY(FATAL, "system resources exhausted"); 
    }
  } /* end of for pthread_create */

  crew_join(crew, TRUE, &statusp);

#ifdef HAVE_SSL
  SSL_thread_cleanup();
#endif

  /**
   * collect all the data from all the threads that
   * were spawned by the run.
   */
  for (x = 0; x < ((crew_get_total(crew) > my.cusers || 
                    crew_get_total(crew)==0 ) ? my.cusers : crew_get_total(crew)); x++) {
    data_increment_count(D, client[x].hits);
    data_increment_bytes(D, client[x].bytes);
    data_increment_total(D, client[x].time);
    data_increment_code (D, client[x].code);
    data_increment_ok200(D, client[x].ok200);
    data_increment_fail (D, client[x].fail);
    data_set_highest    (D, client[x].himark);
    data_set_lowest     (D, client[x].lomark);
    client[x].rand_r_SEED = urandom();
  } /* end of stats accumulation */
  
  /**
   * record stop time
   */
  data_set_stop(D);

  /**
   * cleanup crew
   */ 
  crew_destroy(crew);

  for (x = 0; x < my.cusers; x++) {
    // XXX: TODO
    //digest_challenge_destroy(client[x].auth.wwwchlg);
    //digest_credential_destroy(client[x].auth.wwwcred);
    //digest_challenge_destroy(client[x].auth.proxychlg);
    //digest_credential_destroy(client[x].auth.proxycred);
  }
  array_destroy(my.lurl);
  xfree(client);

  if (my.get) {
    if (data_get_ok200(D) > 0) {
       exit(EXIT_SUCCESS);
    } else {
      if (!my.quiet) echo("[done]\n");
      exit(EXIT_FAILURE);
    }
  }

  /**
   * take a short nap  for  cosmetic  effect
   * this does NOT affect performance stats.
   */
  pthread_usleep_np(10000);
  if (my.verbose)
    fprintf(stderr, "done.\n");
  else
    fprintf(stderr, "\b      done.\n");

  /**
   * prepare and print statistics.
   */
  if (my.failures > 0 && my.failed >= my.failures) {
    fprintf(stderr, "%s aborted due to excessive socket failure; you\n", program_name);
    fprintf(stderr, "can change the failure threshold in $HOME/.%src\n", program_name);
  }
  fprintf(stderr, "\nTransactions:\t\t%12u hits\n",        data_get_count(D));
  fprintf(stderr, "Availability:\t\t%12.2f %%\n",          data_get_count(D)==0 ? 0 :
                                                           (double)data_get_count(D) /
                                                           (data_get_count(D)+my.failed)
                                                           *100
  );
  fprintf(stderr, "Elapsed time:\t\t%12.2f secs\n",        data_get_elapsed(D));
  fprintf(stderr, "Data transferred:\t%12.2f MB\n",        data_get_megabytes(D)); /*%12llu*/
  fprintf(stderr, "Response time:\t\t%12.3f secs\n",       data_get_response_time(D));
  fprintf(stderr, "Transaction rate:\t%12.2f trans/sec\n", data_get_transaction_rate(D));
  fprintf(stderr, "Throughput:\t\t%12.2f MB/sec\n",        data_get_throughput(D));
  fprintf(stderr, "Concurrency:\t\t%12.2f\n",              data_get_concurrency(D));
  fprintf(stderr, "Successful transactions:%12u\n",        data_get_code(D)); 
  if (my.debug) {
    fprintf(stderr, "HTTP OK received:\t%12u\n",             data_get_ok200(D));
  }
  fprintf(stderr, "Failed transactions:\t%12u\n",          my.failed);
  fprintf(stderr, "Longest transaction:\t%12.3f\n",        data_get_highest(D));
  fprintf(stderr, "Shortest transaction:\t%12.3f\n",       data_get_lowest(D));
  fprintf(stderr, " \n");
  if(my.mark)    mark_log_file(my.markstr);
  if(my.logging) log_transaction(D);

  data_destroy(D);
  if (my.url == NULL) {
    for (x = 0; x < my.length; x++)
      xfree(lines->line[x]);
    xfree(lines->line);
    xfree(lines);
  } else {
    xfree(lines->line);
    xfree(lines);
  }

  pthread_mutex_destroy( &(cookie->mutex));

  /** 
   * I should probably take a deeper look 
   * at cookie content to free it but at 
   * this point we're two lines from exit
   */
  xfree (cookie);
  xfree (my.url);

  exit(EXIT_SUCCESS);  
} /* end of int main **/
コード例 #3
0
void send_file(per_request *reqInfo, struct stat *fi, char allow_options) 
{
    FILE *f;
#ifdef BLACKOUT_CODE
    int isblack = FALSE;
#endif /* BLACKOUT_CODE */    

    if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) {
	sprintf(error_msg,"%s to non-script",methods[reqInfo->method]);
	die(reqInfo,SC_NOT_IMPLEMENTED,error_msg);
    }
    set_content_type(reqInfo,reqInfo->filename);

    if((allow_options & OPT_INCLUDES) && (!reqInfo->outh_content_encoding[0])) {
#ifdef XBITHACK
        if((fi->st_mode & S_IXUSR) ||
           (!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE))) {
#else
	if(!strcmp(reqInfo->outh_content_type,INCLUDES_MAGIC_TYPE)) {
#endif /* XBITHACK */
	    reqInfo->bytes_sent = 0;
	    send_parsed_file(reqInfo, allow_options & OPT_INCNOEXEC);
	    log_transaction(reqInfo);
	    return;
	}
    }
    if (reqInfo->path_info[0]) {
	strcat(reqInfo->filename,reqInfo->path_info);
	strcat(reqInfo->url,reqInfo->path_info);
	sprintf(error_msg,"No file matching URL: %s",reqInfo->url);
	log_reason(reqInfo, error_msg, reqInfo->filename);
	die(reqInfo,SC_NOT_FOUND,reqInfo->url);
    }
	
    if(!(f=FOpen(reqInfo->filename,"r"))) {
      if (errno == EACCES) {
	log_reason(reqInfo,"(1) file permissions deny server access",
		   reqInfo->filename);
	/* we've already established that it exists */
	die(reqInfo,SC_FORBIDDEN,reqInfo->url); 
      } else {
	/* We know an error occured, of an unexpected variety. 
	 * This could be due to no more file descriptors.  We have this
	 * child exit after this stage so that errors of state are 
	 * swept under the carpet.
	 */
	standalone = 0;
	sprintf(error_msg,"File Open error, errno=%d",errno);
	log_reason(reqInfo,error_msg,reqInfo->filename);
	die(reqInfo,SC_SERVER_ERROR,error_msg);
      }
    }
    reqInfo->bytes_sent = 0;

#ifdef BLACKOUT_CODE
    if (!strcmp(reqInfo->outh_content_type,BLACKOUT_MAGIC_TYPE)) {
      isblack = TRUE;
      strcpy(reqInfo->outh_content_type,"text/html");
    }
#endif /* BLACKOUT_CODE */

    if(reqInfo->http_version != P_HTTP_0_9) {
      /* No length dependent headers since black is parsed */
#ifdef BLACKOUT_CODE
      if (isblack == FALSE) { 
#endif /* BLACKOUT_CODE */
#ifdef CONTENT_MD5
	reqInfo->outh_content_md5 = (unsigned char *)md5digest(f);
#endif /* CONTENT_MD5 */
	set_content_length(reqInfo,fi->st_size);
	if (set_last_modified(reqInfo,fi->st_mtime)) {
	    FClose(f);
	    return;
	}
      }
      if (reqInfo->http_version != P_HTTP_0_9) {
           send_http_header(reqInfo);
      }
#ifdef BLACKOUT_CODE
    }
#endif /* BLACKOUT_CODE */

    if(reqInfo->method != M_HEAD) {
#ifdef BLACKOUT_CODE
      if (isblack == TRUE)
	send_fp_black(reqInfo,f,NULL);
       else
#endif /* BLACKOUT_CODE */
	send_fp(reqInfo,f,NULL);
    }
    log_transaction(reqInfo);
    FClose(f);
}


void send_dir(per_request *reqInfo,struct stat *finfo, char allow_options) {
  char *name_ptr, *end_ptr;
  char *ifile, *temp_name;

  ifile = newString(HUGE_STRING_LEN,STR_TMP);
  temp_name = newString(HUGE_STRING_LEN,STR_TMP);

/* Path Alias (pa) array should now have the trailing slash */
  /*  if (pa[0] != '/') { */
  if ((reqInfo->filename[strlen(reqInfo->filename) - 1] != '/') && 
      (reqInfo->path_info[0] != '/')) {
    strcpy_dir(ifile,reqInfo->url);
    construct_url(temp_name,reqInfo->hostInfo,ifile);
    escape_url(temp_name);
    die(reqInfo,SC_REDIRECT_PERM,temp_name);
  }

  /* Don't allow PATH_INFO to directory indexes as a compromise for 
     error messages for files which don't exist */

  if ((reqInfo->path_info[0] != '\0') || (strlen(reqInfo->path_info) > 1)) {
        strcat(reqInfo->filename,reqInfo->path_info);
        strcat(reqInfo->url,reqInfo->path_info);
        sprintf(error_msg,"No file matching URL: %s",reqInfo->url);
        log_reason(reqInfo, error_msg, reqInfo->filename);
	freeString(temp_name);
	freeString(ifile);
        die(reqInfo,SC_NOT_FOUND,reqInfo->url);
  }
    
  strncpy(temp_name, reqInfo->hostInfo->index_names, HUGE_STRING_LEN-1);
  end_ptr = name_ptr = temp_name;

  while (*name_ptr) {
    
    while (*name_ptr && isspace (*name_ptr)) ++name_ptr;
    end_ptr = name_ptr;
    if (strchr(end_ptr, ' ') ) {
      end_ptr = strchr(name_ptr, ' ');
      *end_ptr = '\0';
      end_ptr++;
    } else
      end_ptr += strlen(end_ptr);
    make_full_path(reqInfo->filename,name_ptr,ifile);
    if(stat(ifile,finfo) == -1) {
      if(! *end_ptr && (allow_options & OPT_INDEXES)) {
        if (reqInfo->path_info[0]) {
          strcat(reqInfo->filename,reqInfo->path_info);
	  strcat(reqInfo->url,reqInfo->path_info);
	  log_reason(reqInfo,"file does not exist",reqInfo->filename);
	  freeString(ifile);
	  freeString(temp_name);
	  die(reqInfo,SC_NOT_FOUND,reqInfo->url);
	}
	if ((reqInfo->method != M_GET) && (reqInfo->method != M_HEAD)) {
	  sprintf(error_msg,"%s to non-script",methods[reqInfo->method]);
	  freeString(ifile);
	  freeString(temp_name);
	  die(reqInfo,SC_NOT_IMPLEMENTED,error_msg);
	}	
	index_directory(reqInfo);
	freeString(ifile);
	freeString(temp_name);
	return;
      } else if (! *end_ptr) {
	log_reason(reqInfo,"(2) file permissions deny server access",
		   reqInfo->filename);
	freeString(ifile);
	freeString(temp_name);
	die(reqInfo,SC_FORBIDDEN,reqInfo->url);
      }
    } else {
      strcpy(reqInfo->filename,ifile);
      probe_content_type(reqInfo,reqInfo->filename);
      if(!strcmp(reqInfo->outh_content_type,CGI_MAGIC_TYPE))
	send_cgi(reqInfo,finfo,allow_options);
      else
	send_file(reqInfo,finfo,allow_options);
      freeString(ifile);
      freeString(temp_name);
      return;
    }
    name_ptr = end_ptr;
  }	 
}