/* This function creates the (default) directory configuration. Well, we have * no defaults to set so we simply alloc the memory... */ static void* mapserver_create_dir_config (apr_pool_t *p, char *dir) { mapserver_dir_config *newconf; newconf = (mapserver_dir_config*) apr_pcalloc (p, sizeof (mapserver_dir_config)); newconf->config_pool = p; newconf->uri = apr_pstrdup (p, dir); newconf->map = NULL; newconf->mapfile_name = NULL; newconf->mtime = apr_time_from_sec (0); if (dir) { int len = strlen (dir); if (len > 1 && dir [len - 1] == '/' ) newconf->uri [len - 1] = '\0'; } return newconf; }
APREQ_DECLARE(void) apreq_cookie_expires(apreq_cookie_t *c, const char *time_str) { if (time_str == NULL) { c->max_age = -1; return; } if (!strcasecmp(time_str, "now")) c->max_age = 0; else { c->max_age = apr_date_parse_rfc(time_str); if (c->max_age == APR_DATE_BAD) c->max_age = apr_time_from_sec(apreq_atoi64t(time_str)); else c->max_age -= apr_time_now(); } }
static void do_write(void) { apr_file_t *file; apr_status_t rv; if (apr_file_open(&file, testfile, APR_WRITE|APR_CREATE, APR_OS_DEFAULT, pool) != APR_SUCCESS) errmsg("Could not create file.\n"); printf("Test file created.\n"); if ((rv = apr_file_lock(file, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS) errmsg2("Could not lock the file", rv); printf("Lock created.\nSleeping..."); fflush(stdout); apr_sleep(apr_time_from_sec(30)); (void) apr_file_close(file); printf(" done.\nExiting.\n"); }
/* do a HTTP/1.1 age calculation */ CACHE_DECLARE(apr_int64_t) ap_cache_current_age(cache_info *info, const apr_time_t age_value, apr_time_t now) { apr_time_t apparent_age, corrected_received_age, response_delay, corrected_initial_age, resident_time, current_age, age_value_usec; age_value_usec = apr_time_from_sec(age_value); /* Perform an HTTP/1.1 age calculation. (RFC2616 13.2.3) */ apparent_age = MAX(0, info->response_time - info->date); corrected_received_age = MAX(apparent_age, age_value_usec); response_delay = info->response_time - info->request_time; corrected_initial_age = corrected_received_age + response_delay; resident_time = now - info->response_time; current_age = corrected_initial_age + resident_time; return apr_time_sec(current_age); }
static int msgwait(int sleep_sec, int first_box, int last_box) { int i; int recvd = 0; apr_time_t start = apr_time_now(); apr_interval_time_t sleep_duration = apr_time_from_sec(sleep_sec); while (apr_time_now() - start < sleep_duration) { for (i = first_box; i < last_box; i++) { if (boxes[i].msgavail && !strcmp(boxes[i].msg, MSG)) { recvd++; boxes[i].msgavail = 0; /* reset back to 0 */ /* reset the msg field. 1024 is a magic number and it should * be a macro, but I am being lazy. */ memset(boxes[i].msg, 0, 1024); } } apr_sleep(apr_time_make(0, 10000)); /* 10ms */ } return recvd; }
void *rss_check_thread(apr_thread_t *th, void *data) { resource_service_fn_t *rs = (resource_service_fn_t *)data; rs_simple_priv_t *rss = (rs_simple_priv_t *)rs->priv; int do_notify, map_version, status_change; apr_interval_time_t dt; dt = apr_time_from_sec(rss->check_interval); apr_thread_mutex_lock(rss->lock); rss->current_check = 0; //** Triggers a reload do { log_printf(5, "LOOP START\n"); _rs_simple_refresh(rs); //** Do a quick check and see if the file has changed do_notify = 0; if (rss->current_check != rss->modify_time) { //** Need to reload rss->current_check = rss->modify_time; do_notify = 1; // _rss_make_check_table(rs); } map_version = rss->modify_time; apr_thread_mutex_unlock(rss->lock); status_change = (rss->check_timeout <= 0) ? 0 : rss_perform_check(rs); if (((do_notify == 1) && (rss->dynamic_mapping == 1)) || (status_change != 0)) rss_mapping_notify(rs, map_version, status_change); log_printf(5, "LOOP END\n"); apr_thread_mutex_lock(rss->lock); if (rss->shutdown == 0) apr_thread_cond_timedwait(rss->cond, rss->lock, dt); } while (rss->shutdown == 0); //** Clean up _rss_clear_check_table(rss->ds, rss->rid_mapping, rss->mpool); apr_thread_mutex_unlock(rss->lock); return(NULL); }
/** * Creates a new auth_vas_cache, allocated from the given memory pool * because the vas_ctx_t must be the same. * * The vas_ctx and vas_serverid are convenience pointers for cache users -- they * can be NULL or unused if the cached items don't need them. * * @param parent_pool Memory pool to be used as the parent of the cache's pool. * @param vas_ctx libvas context to be used by cached items. * @param vas_serverid Server ID to associate with cached items (optional). * @param unref_cb Function to call immediately after removing an item from the * cache, for example to free or unref an object. May be NULL. * @param get_key_cb Function to get the item's key. See the auth_vas_cache * documentation for details. */ auth_vas_cache * auth_vas_cache_new(apr_pool_t *parent_pool, vas_ctx_t *vas_ctx, vas_id_t *vas_serverid, void (*ref_cb)(void *), void (*unref_cb)(void *), const char *(*get_key_cb)(void *)) { auth_vas_cache *cache = NULL; apr_status_t aprerr; /* Should we allocate the cache out of the cache subpool instead? * Only necessary if caches are destroyed more frequently than processes * exit. */ cache = apr_pcalloc(parent_pool, sizeof(*cache)); if (!cache) { MAV_LOG_P(APLOG_ERR, parent_pool, "Failed to allocate cache structure"); return NULL; } aprerr = apr_pool_create(&cache->pool, parent_pool); if (aprerr) { MAV_LOG_PERRNO(APLOG_ERR, parent_pool, aprerr, "Failed to create cache memory pool"); return NULL; } cache->table = apr_hash_make(cache->pool); cache->vas_ctx = vas_ctx; cache->vas_serverid = vas_serverid; cache->ref_item_cb = ref_cb; cache->unref_item_cb = unref_cb; cache->get_key_cb = get_key_cb; cache->max_age_us = apr_time_from_sec(DEFAULT_EXPIRE_SECONDS); cache->max_size = DEFAULT_MAX_CACHE_SIZE; return cache; }
static void read_write(abts_case *tc, void *data) { apr_status_t rv; char *buf; apr_size_t nbytes; nbytes = strlen("this is a test"); buf = (char *)apr_palloc(p, nbytes + 1); rv = apr_file_pipe_create(&readp, &writep, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_PTR_NOTNULL(tc, readp); ABTS_PTR_NOTNULL(tc, writep); rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1)); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); if (!rv) { rv = apr_file_read(readp, buf, &nbytes); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); ABTS_INT_EQUAL(tc, 0, nbytes); } }
static void read_write(CuTest *tc) { apr_status_t rv; char *buf; apr_size_t nbytes; nbytes = strlen("this is a test"); buf = (char *)apr_palloc(p, nbytes + 1); rv = apr_file_pipe_create(&readp, &writep, p); CuAssertIntEquals(tc, APR_SUCCESS, rv); CuAssertPtrNotNull(tc, readp); CuAssertPtrNotNull(tc, writep); rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1)); CuAssertIntEquals(tc, APR_SUCCESS, rv); rv = apr_file_read(readp, buf, &nbytes); if (!rv) { CuAssertIntEquals(tc, 1, APR_STATUS_IS_TIMEUP(rv)); CuAssertIntEquals(tc, 0, nbytes); } }
static void test_timeoutcond(abts_case *tc, void *data) { apr_status_t s; apr_interval_time_t timeout; apr_time_t begin, end; int i; s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, s); ABTS_PTR_NOTNULL(tc, timeout_mutex); s = apr_thread_cond_create(&timeout_cond, p); ABTS_INT_EQUAL(tc, APR_SUCCESS, s); ABTS_PTR_NOTNULL(tc, timeout_cond); timeout = apr_time_from_sec(5); for (i = 0; i < MAX_RETRY; i++) { apr_thread_mutex_lock(timeout_mutex); begin = apr_time_now(); s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout); end = apr_time_now(); apr_thread_mutex_unlock(timeout_mutex); if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) { continue; } ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s)); ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 500000); break; } ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY); APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional", apr_thread_cond_destroy(timeout_cond)); }
static logsql_query_ret safe_sql_insert(request_rec *r, logsql_tabletype table_type, const char *table_name, const char *query) { logsql_query_ret result; logsql_state *cls = ap_get_module_config(r->server->module_config, &log_sql_module); if (!global_config.db.connected || global_config.driver == NULL) { /* preserve query */ return LOGSQL_QUERY_NOLINK; } result = global_config.driver->insert(r,&global_config.db,query); /* If we ran the query and it returned an error, try to be robust. * (After all, the module thought it had a valid mysql_log connection but the query * could have failed for a number of reasons, so we have to be extra-safe and check.) */ switch (result) { case LOGSQL_QUERY_SUCCESS: return LOGSQL_QUERY_SUCCESS; case LOGSQL_QUERY_NOLINK: return LOGSQL_QUERY_FAIL; /* TODO: What do we do here */ case LOGSQL_QUERY_FAIL: global_config.driver->disconnect(&global_config.db); global_config.db.connected = 0; /* re-open the connection and try again */ if (log_sql_opendb_link(r->server) != LOGSQL_OPENDB_FAIL) { log_error(APLOG_MARK,APLOG_NOTICE,0, r->server,"db reconnect successful"); # if defined(WITH_APACHE20) apr_sleep(apr_time_from_sec(0.25)); /* pause for a quarter second */ # elif defined(WITH_APACHE13) # if defined(WIN32) Sleep((DWORD)0.25); # else { struct timespec delay, remainder; int nanoret; delay.tv_sec = 0; delay.tv_nsec = 250000000; /* pause for a quarter second */ nanoret = nanosleep(&delay, &remainder); if (nanoret && errno != EINTR) { log_error(APLOG_MARK,APLOG_ERR, errno, r->server,"nanosleep unsuccessful"); } } # endif /* win32 */ # endif result = global_config.driver->insert(r,&global_config.db,query); if (result == LOGSQL_QUERY_SUCCESS) { return LOGSQL_QUERY_SUCCESS; } else { log_error(APLOG_MARK,APLOG_ERR,0,r->server,"second attempt failed"); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } } else { log_error(APLOG_MARK,APLOG_ERR,0,r->server, "reconnect failed, unable to reach database. SQL logging stopped until child regains a db connection."); log_error(APLOG_MARK,APLOG_ERR,0,r->server, "log entries are being preserved in %s",cls->preserve_file); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } break; case LOGSQL_QUERY_NOTABLE: if (global_config.createtables) { log_error(APLOG_MARK,APLOG_ERR,0,r->server, "table doesn't exist...creating now"); if ((result = global_config.driver->create_table(r, &global_config.db, table_type, table_name))!=LOGSQL_TABLE_SUCCESS) { log_error(APLOG_MARK,APLOG_ERR,result,r->server, "child attempted but failed to create one or more tables for %s, preserving query", ap_get_server_name(r)); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } else { log_error(APLOG_MARK,APLOG_ERR,result, r->server, "tables successfully created - retrying query"); if ((result = global_config.driver->insert(r,&global_config.db,query))!=LOGSQL_QUERY_SUCCESS) { log_error(APLOG_MARK,APLOG_ERR,result, r->server, "giving up, preserving query"); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } else { log_error(APLOG_MARK,APLOG_NOTICE,0, r->server, "query successful after table creation"); return LOGSQL_QUERY_SUCCESS; } } } else { log_error(APLOG_MARK,APLOG_ERR,0,r->server, "table doesn't exist, creation denied by configuration, preserving query"); preserve_entry(r, query); return LOGSQL_QUERY_PRESERVED; } break; default: log_error(APLOG_MARK,APLOG_ERR,0, r->server, "Invalid return code from mog_log_query"); return LOGSQL_QUERY_FAIL; break; } return LOGSQL_QUERY_FAIL; }
AP_DECLARE(void) ap_reclaim_child_processes(int terminate, ap_reclaim_callback_fn_t *mpm_callback) { apr_time_t waittime = 1024 * 16; int i; extra_process_t *cur_extra; int not_dead_yet; int max_daemons; apr_time_t starttime = apr_time_now(); /* this table of actions and elapsed times tells what action is taken * at which elapsed time from starting the reclaim */ struct { action_t action; apr_time_t action_time; } action_table[] = { {DO_NOTHING, 0}, /* dummy entry for iterations where we reap * children but take no action against * stragglers */ {SEND_SIGTERM, apr_time_from_sec(3)}, {SEND_SIGTERM, apr_time_from_sec(5)}, {SEND_SIGTERM, apr_time_from_sec(7)}, {SEND_SIGKILL, apr_time_from_sec(9)}, {GIVEUP, apr_time_from_sec(10)} }; int cur_action; /* index of action we decided to take this * iteration */ int next_action = 1; /* index of first real action */ ap_mpm_query(AP_MPMQ_MAX_DAEMON_USED, &max_daemons); do { apr_sleep(waittime); /* don't let waittime get longer than 1 second; otherwise, we don't * react quickly to the last child exiting, and taking action can * be delayed */ waittime = waittime * 4; if (waittime > apr_time_from_sec(1)) { waittime = apr_time_from_sec(1); } /* see what action to take, if any */ if (action_table[next_action].action_time <= apr_time_now() - starttime) { cur_action = next_action; ++next_action; } else { cur_action = 0; /* nothing to do */ } /* now see who is done */ not_dead_yet = 0; for (i = 0; i < max_daemons; ++i) { process_score *ps = ap_get_scoreboard_process(i); pid_t pid = ps->pid; if (pid == 0) { continue; /* not every scoreboard entry is in use */ } if (reclaim_one_pid(pid, action_table[cur_action].action)) { mpm_callback(i, 0, 0); } else { ++not_dead_yet; } } cur_extra = extras; while (cur_extra) { ap_generation_t old_gen; extra_process_t *next = cur_extra->next; if (reclaim_one_pid(cur_extra->pid, action_table[cur_action].action)) { if (ap_unregister_extra_mpm_process(cur_extra->pid, &old_gen) == 1) { mpm_callback(-1, cur_extra->pid, old_gen); } else { AP_DEBUG_ASSERT(1 == 0); } } else { ++not_dead_yet; } cur_extra = next; } #if APR_HAS_OTHER_CHILD apr_proc_other_child_refresh_all(APR_OC_REASON_RESTART); #endif } while (not_dead_yet > 0 && action_table[cur_action].action != GIVEUP); }
int main(int argc, char *argv[]) { apr_pool_t *p; apr_socket_t *sock; apr_status_t rv; apr_sockaddr_t *remote_sa; apr_initialize(); atexit(apr_terminate); apr_pool_create(&p, NULL); if (argc < 3) { exit(-1); } rv = apr_sockaddr_info_get(&remote_sa, argv[2], APR_UNSPEC, 8021, 0, p); if (rv != APR_SUCCESS) { exit(-1); } if (apr_socket_create(&sock, remote_sa->family, SOCK_STREAM, 0, p) != APR_SUCCESS) { exit(-1); } rv = apr_socket_timeout_set(sock, apr_time_from_sec(3)); if (rv) { exit(-1); } apr_socket_connect(sock, remote_sa); if (!strcmp("read", argv[1])) { char datarecv[STRLEN]; apr_size_t length = STRLEN; apr_status_t rv; memset(datarecv, 0, STRLEN); rv = apr_socket_recv(sock, datarecv, &length); apr_socket_close(sock); if (APR_STATUS_IS_TIMEUP(rv)) { exit(SOCKET_TIMEOUT); } if (strcmp(datarecv, DATASTR)) { exit(-1); } exit((int)length); } else if (!strcmp("write", argv[1]) || !strcmp("write_after_delay", argv[1])) { apr_size_t length = strlen(DATASTR); if (!strcmp("write_after_delay", argv[1])) { apr_sleep(apr_time_from_sec(2)); } apr_socket_send(sock, DATASTR, &length); apr_socket_close(sock); exit((int)length); } else if (!strcmp("close", argv[1])) { apr_socket_close(sock); exit(0); } exit(-1); }
void auth_vas_cache_set_max_age(auth_vas_cache *cache, unsigned int seconds) { cache->max_age_us = apr_time_from_sec(seconds); }
mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_request_get_tile *req_tile) { int expires = 0; mapcache_http_response *response; int i,first = -1; int ntiles_with_data = 0; char *timestr; mapcache_image *base=NULL,*overlay; mapcache_image_format *format = NULL; #ifdef DEBUG if(req_tile->ntiles ==0) { ctx->set_error(ctx,500,"BUG: get_tile called with 0 tiles"); return NULL; } #endif expires = 0; response = mapcache_http_response_create(ctx->pool); mapcache_prefetch_tiles(ctx,req_tile->tiles,req_tile->ntiles); if(GC_HAS_ERROR(ctx)) return NULL; /* count how many tiles actually contain data */ for(i=0; i<req_tile->ntiles; i++) { /* add 1 if tile->nodata == 0 */ ntiles_with_data -= req_tile->tiles[i]->nodata - 1; } if(ntiles_with_data == 0) { ctx->set_error(ctx,404, "no tiles containing image data could be retrieved (not in cache, and read-only tileset or no source configured)"); return NULL; } /* this loop retrieves the tiles from the caches, and eventually decodes and merges them together * if multiple tiles were asked for */ for(i=0; i<req_tile->ntiles; i++) { mapcache_tile *tile = req_tile->tiles[i]; if(tile->nodata) continue; if(first == -1) { first = i; response->mtime = tile->mtime; expires = tile->expires; /* if we have multiple tiles to merge, decode the image data */ if(ntiles_with_data>1) { if(!tile->raw_image) { tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data); if(!tile->raw_image) return NULL; } base = tile->raw_image; } } else { if(response->mtime < tile->mtime) response->mtime = tile->mtime; if(tile->expires < expires) { expires = tile->expires; } if(!tile->raw_image) { tile->raw_image = mapcache_imageio_decode(ctx, tile->encoded_data); if(!tile->raw_image) return NULL; } overlay = tile->raw_image; mapcache_image_merge(ctx, base, overlay); if(GC_HAS_ERROR(ctx)) { return NULL; } } } format = NULL; /* if we had more than one tile, we need to encode the raw image data into a mapcache_buffer */ if(ntiles_with_data > 1) { if(req_tile->format) { format = req_tile->format; } else { format = req_tile->tiles[first]->tileset->format; if(!format) { format = ctx->config->default_image_format; /* this one is always defined */ } } response->data = format->write(ctx, base, format); if(GC_HAS_ERROR(ctx)) { return NULL; } } else { response->data = req_tile->tiles[first]->encoded_data; format = req_tile->tiles[first]->tileset->format; } /* compute the content-type */ if(format && format->mime_type) { apr_table_set(response->headers,"Content-Type",format->mime_type); } else { mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,response->data); if(t == GC_PNG) apr_table_set(response->headers,"Content-Type","image/png"); else if(t == GC_JPEG) apr_table_set(response->headers,"Content-Type","image/jpeg"); } /* compute expiry headers */ if(expires) { apr_time_t now = apr_time_now(); apr_time_t additional = apr_time_from_sec(expires); apr_time_t texpires = now + additional; apr_table_set(response->headers, "Cache-Control",apr_psprintf(ctx->pool, "max-age=%d", expires)); timestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN); apr_rfc822_date(timestr, texpires); apr_table_setn(response->headers, "Expires", timestr); } return response; }
static void test_mech_mode(apr_lockmech_e mech, const char *mech_name, test_mode_e test_mode) { apr_thread_t *threads[20]; int numThreads = 5; int i; apr_status_t rv; printf("Trying %s mutexes with mechanism `%s'...\n", test_mode == TEST_GLOBAL ? "global" : "proc", mech_name); assert(numThreads <= sizeof(threads) / sizeof(threads[0])); assert(apr_pool_create(&p, NULL) == APR_SUCCESS); assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS); assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS); lock_init(mech, test_mode); counter = 0; i = 0; while (i < numThreads) { rv = apr_thread_create(&threads[i], NULL, eachThread, (void *)test_mode, p); if (rv != APR_SUCCESS) { fprintf(stderr, "apr_thread_create->%d\n", rv); exit(1); } ++i; } apr_sleep(apr_time_from_sec(5)); if (test_mode == TEST_PROC) { printf(" Mutex mechanism `%s' is %sglobal in scope on this platform.\n", mech_name, counter == 1 ? "" : "not "); } else { if (counter != 1) { fprintf(stderr, "\n!!!apr_global_mutex operations are broken on this " "platform for mutex mechanism `%s'!\n" "They don't block out threads within the same process.\n", mech_name); fprintf(stderr, "counter value: %d\n", counter); exit(1); } else { printf(" no problems encountered...\n"); } } assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS); i = 0; while (i < numThreads) { apr_status_t ignored; rv = apr_thread_join(&ignored, threads[i]); assert(rv == APR_SUCCESS); ++i; } lock_destroy(test_mode); apr_thread_mutex_destroy(thread_mutex); apr_pool_destroy(p); }
// See here for the structure of request_rec: // http://ci.apache.org/projects/httpd/trunk/doxygen/structrequest__rec.html static int hook(request_rec *r) { settings_rec *cfg = ap_get_module_config( r->per_dir_config, &querystring2cookie_module ); /* Do not run in subrequests, don't run if not enabled */ if( !(cfg->enabled || r->main) ) { return DECLINED; } /* No query string? nothing to do here */ if( !(r->args) || strlen( r->args ) < 1 ) { return DECLINED; } /* skip if dnt headers are present? */ if( !(cfg->enabled_if_dnt) && apr_table_get( r->headers_in, "DNT" ) ) { _DEBUG && fprintf( stderr, "DNT header sent: declined\n" ); return DECLINED; } _DEBUG && fprintf( stderr, "Query string: '%s'\n", r->args ); // *********************************** // Calculate expiry time // *********************************** // The expiry time. We can't use max-age because IE6 - IE8 do not // support it :( char *expires = ""; if( cfg->cookie_expires > 0 ) { apr_time_exp_t tms; apr_time_exp_gmt( &tms, r->request_time + apr_time_from_sec( cfg->cookie_expires ) ); expires = apr_psprintf( r->pool, "expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", apr_day_snames[tms.tm_wday], tms.tm_mday, apr_month_snames[tms.tm_mon], tms.tm_year % 100, tms.tm_hour, tms.tm_min, tms.tm_sec ); } // *********************************** // Find key/value pairs // *********************************** // keep track of how much data we've been writing - there's a limit to how // much a browser will store per domain (usually 4k) so we want to make sure // it's not getting flooded. int total_pair_size = 0; // This holds the final cookie we'll send back - make sure to initialize // or it can point at garbage! char *cookie = ""; // string to use as the cookie name (together with the prefix) - make sure to // initialize or it can point at garbage! char *cookie_name = ""; // Iterate over the key/value pairs char *last_pair; char *pair = apr_strtok( apr_pstrdup( r->pool, r->args ), "&", &last_pair ); _DEBUG && fprintf( stderr, "about to parse query string for pairs\n" ); _DEBUG && fprintf( stderr, "looking for cookie name in %s\n", cfg->cookie_name_from ); while( pair != NULL ) { // length of the substr before the = sign (or index of the = sign) int contains_equals_at = strcspn( pair, "=" ); // Does not contains a =, or starts with a =, meaning it's garbage if( !strstr(pair, "=") || contains_equals_at < 1 ) { _DEBUG && fprintf( stderr, "invalid pair: %s\n", pair ); // And get the next pair -- has to be done at every break pair = apr_strtok( NULL, "&", &last_pair ); continue; } _DEBUG && fprintf( stderr, "pair looks valid: %s - = sign at pos: %i\n", pair, contains_equals_at ); // So this IS a key value pair. Let's get the key and the value. // first, get the key - everything up to the first = char *key = apr_pstrndup( r->pool, pair, contains_equals_at ); // now get the value, everything AFTER the = sign. We do that by // moving the pointer past the = sign. char *value = apr_pstrdup( r->pool, pair ); value += contains_equals_at + 1; _DEBUG && fprintf( stderr, "pair=%s, key=%s, value=%s\n", pair, key, value ); // you want us to use a name from the query string? // This might be that name. if( cfg->cookie_name_from && !(strlen(cookie_name)) && strcasecmp( key, cfg->cookie_name_from ) == 0 ) { // get everything after the = sign -- that's our name. cookie_name = apr_pstrcat( r->pool, cfg->cookie_prefix, value, NULL ); _DEBUG && fprintf( stderr, "using %s as the cookie name\n", cookie_name ); // And get the next pair -- has to be done at every break pair = apr_strtok( NULL, "&", &last_pair ); continue; // may be on the ignore list } else { // may have to continue the outer loop, use this as a marker int do_continue = 0; // you might have blacklisted this key; let's check // Following tutorial code here again: // http://dev.ariel-networks.com/apr/apr-tutorial/html/apr-tutorial-19.html int i; for( i = 0; i < cfg->qs_ignore->nelts; i++ ) { char *ignore = ((char **)cfg->qs_ignore->elts)[i]; _DEBUG && fprintf( stderr, "processing ignore %s against pair %s\n", ignore, pair ); // it's indeed on the ignore list; move on // do this by comparing the string length first - if the length of // the ignore key and the key are identical AND the first N characters // of the string are the same if( strcasecmp( key, ignore ) == 0 ) { _DEBUG && fprintf( stderr, "pair %s is on the ignore list: %s\n", pair, ignore ); // signal to continue the outer loop; we found an ignore match do_continue = 1; break; } } // ignore match found, move on if( do_continue ) { // And get the next pair -- has to be done at every break pair = apr_strtok( NULL, "&", &last_pair ); continue; } } // looks like a valid key=value declaration _DEBUG && fprintf( stderr, "valid key/value pair: %s\n", pair ); // Now, the key may contain URL unsafe characters, which are also // not allowed in Cookies. See here: // http://tools.ietf.org/html/rfc2068, section 2.2 on 'tspecials' // // So instead, we url encode the key. The size of the key is max // 3 times old key size (any char gets encoded into %xx), so allow // for that space. See the documentation here: // http://httpd.apache.org/apreq/docs/libapreq2/apreq__util_8h.html#785be2ceae273b0a7b2ffda223b2ebae char *escaped_key = apreq_escape( r->pool, key, strlen(key) ); char *escaped_value = apreq_escape( r->pool, value, strlen(value) ); _DEBUG && fprintf( stderr, "Original key: %s - Escaped key: %s\n", key, escaped_key ); _DEBUG && fprintf( stderr, "Original value: %s - Escaped value: %s\n", value, escaped_value ); // Now, let's do some transposing: The '=' sign needs to be replaced // with whatever the separator is. It can't be a '=' sign, as that's // illegal in cookies. The string may be larger than a single char, // so split the string and do the magix. // This makes key[delim]value - redefining pair here is safe, we're // just using it for printing now. char *key_value = apr_pstrcat( r->pool, escaped_key, cfg->cookie_key_value_delimiter, escaped_value, NULL ); int this_pair_size = strlen( key_value ); // Make sure the individual pair, as well as the whole thing doesn't // get too long _DEBUG && fprintf( stderr, "this pair size: %i, total pair size: %i, max size: %i\n", this_pair_size, total_pair_size, cfg->cookie_max_size ); if( (this_pair_size <= cfg->cookie_max_size) && (total_pair_size + this_pair_size <= cfg->cookie_max_size) ) { cookie = apr_pstrcat( r->pool, cookie, // the cookie so far // If we already have pairs in here, we need the // delimiter, otherwise we don't. (strlen(cookie) ? cfg->cookie_pair_delimiter : ""), key_value, // the next pair. NULL ); // update the book keeping - this is the new size including delims total_pair_size = strlen(cookie); _DEBUG && fprintf( stderr, "this pair size: %i, total pair size: %i\n", this_pair_size, total_pair_size ); } else { _DEBUG && fprintf( stderr, "Pair size too long to add: %s (this: %i total: %i max: %i)\n", key_value, this_pair_size, total_pair_size, cfg->cookie_max_size ); } // and move the pointer pair = apr_strtok( NULL, "&", &last_pair ); } // So you told us we should use a cookie name from the query string, // but we never found it in there. That's a problem. if( cfg->cookie_name_from && !strlen(cookie_name) ) { // r->err_headers_out also honors non-2xx responses and // internal redirects. See the patch here: // http://svn.apache.org/viewvc?view=revision&revision=1154620 apr_table_addn( r->err_headers_out, "X-QS2Cookie", apr_pstrcat( r->pool, "ERROR: Did not detect cookie name - missing QS argument: ", cfg->cookie_name_from, NULL ) ); // Let's return the output } else { // we got here without a cookie name? We can use the default. if( !strlen(cookie_name) ) { _DEBUG && fprintf( stderr, "explicitly setting cookie name to: %s\n", cfg->cookie_name ); cookie_name = apr_pstrcat( r->pool, cfg->cookie_prefix, cfg->cookie_name, NULL ); } _DEBUG && fprintf( stderr, "cookie name: %s\n", cookie_name ); // XXX use a sprintf format for more flexibility? if( cfg->encode_in_key ) { _DEBUG && fprintf( stderr, "%s: encoding in the key\n", cookie_name ); cookie = apr_pstrcat( r->pool, // cookie data cookie_name, cfg->cookie_pair_delimiter, cookie, "=", // The format is different on 32 (%ld) vs 64bit (%lld), so // use the constant for it instead. You can find this in apr.h apr_psprintf( r->pool, "%" APR_OFF_T_FMT, apr_time_sec(apr_time_now()) ), NULL ); } else { _DEBUG && fprintf( stderr, "%s: encoding in the value\n", cookie_name ); cookie = apr_pstrcat( r->pool, cookie_name, "=", cookie, NULL ); } // And now add the meta data to the cookie cookie = apr_pstrcat( r->pool, cookie, "; ", "path=/; ", cfg->cookie_domain, expires, NULL ); _DEBUG && fprintf( stderr, "cookie: %s\n", cookie ); // r->err_headers_out also honors non-2xx responses and // internal redirects. See the patch here: // http://svn.apache.org/viewvc?view=revision&revision=1154620 apr_table_addn( r->err_headers_out, "Set-Cookie", cookie ); } return OK; }
int main (int argc, const char * const argv[]) { char buf[BUFSIZE]; apr_size_t nRead, nWrite; apr_file_t *f_stdin; apr_file_t *f_stdout; apr_getopt_t *opt; apr_status_t rv; char c; const char *opt_arg; const char *err = NULL; #if APR_FILES_AS_SOCKETS apr_pollfd_t pollfd = { 0 }; apr_status_t pollret = APR_SUCCESS; int polltimeout; #endif apr_app_initialize(&argc, &argv, NULL); atexit(apr_terminate); memset(&config, 0, sizeof config); memset(&status, 0, sizeof status); status.rotateReason = ROTATE_NONE; apr_pool_create(&status.pool, NULL); apr_getopt_init(&opt, status.pool, argc, argv); #if APR_FILES_AS_SOCKETS while ((rv = apr_getopt(opt, "lL:p:ftvecn:", &c, &opt_arg)) == APR_SUCCESS) { #else while ((rv = apr_getopt(opt, "lL:p:ftven:", &c, &opt_arg)) == APR_SUCCESS) { #endif switch (c) { case 'l': config.use_localtime = 1; break; case 'L': config.linkfile = opt_arg; break; case 'p': config.postrotate_prog = opt_arg; break; case 'f': config.force_open = 1; break; case 't': config.truncate = 1; break; case 'v': config.verbose = 1; break; case 'e': config.echo = 1; break; #if APR_FILES_AS_SOCKETS case 'c': config.create_empty = 1; break; #endif case 'n': config.num_files = atoi(opt_arg); status.fileNum = -1; break; } } if (rv != APR_EOF) { usage(argv[0], NULL /* specific error message already issued */ ); } /* * After the initial flags we need 2 to 4 arguments, * the file name, either the rotation interval time or size * or both of them, and optionally the UTC offset. */ if ((argc - opt->ind < 2) || (argc - opt->ind > 4) ) { usage(argv[0], "Incorrect number of arguments"); } config.szLogRoot = argv[opt->ind++]; /* Read in the remaining flags, namely time, size and UTC offset. */ for(; opt->ind < argc; opt->ind++) { if ((err = get_time_or_size(&config, argv[opt->ind], opt->ind < argc - 1 ? 0 : 1)) != NULL) { usage(argv[0], err); } } config.use_strftime = (strchr(config.szLogRoot, '%') != NULL); if (config.use_strftime && config.num_files > 0) { fprintf(stderr, "Cannot use -n with %% in filename\n"); exit(1); } if (status.fileNum == -1 && config.num_files < 1) { fprintf(stderr, "Invalid -n argument\n"); exit(1); } if (apr_file_open_stdin(&f_stdin, status.pool) != APR_SUCCESS) { fprintf(stderr, "Unable to open stdin\n"); exit(1); } if (apr_file_open_stdout(&f_stdout, status.pool) != APR_SUCCESS) { fprintf(stderr, "Unable to open stdout\n"); exit(1); } /* * Write out result of config parsing if verbose is set. */ if (config.verbose) { dumpConfig(&config); } #if APR_FILES_AS_SOCKETS if (config.create_empty && config.tRotation) { pollfd.p = status.pool; pollfd.desc_type = APR_POLL_FILE; pollfd.reqevents = APR_POLLIN; pollfd.desc.f = f_stdin; } #endif /* * Immediately open the logfile as we start, if we were forced * to do so via '-f'. */ if (config.force_open) { doRotate(&config, &status); } for (;;) { nRead = sizeof(buf); #if APR_FILES_AS_SOCKETS if (config.create_empty && config.tRotation) { polltimeout = status.tLogEnd ? status.tLogEnd - get_now(&config) : config.tRotation; if (polltimeout <= 0) { pollret = APR_TIMEUP; } else { pollret = apr_poll(&pollfd, 1, &pollret, apr_time_from_sec(polltimeout)); } } if (pollret == APR_SUCCESS) { rv = apr_file_read(f_stdin, buf, &nRead); if (APR_STATUS_IS_EOF(rv)) { break; } else if (rv != APR_SUCCESS) { exit(3); } } else if (pollret == APR_TIMEUP) { *buf = 0; nRead = 0; } else { fprintf(stderr, "Unable to poll stdin\n"); exit(5); } #else /* APR_FILES_AS_SOCKETS */ rv = apr_file_read(f_stdin, buf, &nRead); if (APR_STATUS_IS_EOF(rv)) { break; } else if (rv != APR_SUCCESS) { exit(3); } #endif /* APR_FILES_AS_SOCKETS */ checkRotate(&config, &status); if (status.rotateReason != ROTATE_NONE) { doRotate(&config, &status); } nWrite = nRead; rv = apr_file_write_full(status.current.fd, buf, nWrite, &nWrite); if (nWrite != nRead) { apr_off_t cur_offset; cur_offset = 0; if (apr_file_seek(status.current.fd, APR_CUR, &cur_offset) != APR_SUCCESS) { cur_offset = -1; } status.nMessCount++; apr_snprintf(status.errbuf, sizeof status.errbuf, "Error %d writing to log file at offset %" APR_OFF_T_FMT ". " "%10d messages lost (%pm)\n", rv, cur_offset, status.nMessCount, &rv); truncate_and_write_error(&status); } else { status.nMessCount++; } if (config.echo) { if (apr_file_write_full(f_stdout, buf, nRead, &nWrite)) { fprintf(stderr, "Unable to write to stdout\n"); exit(4); } } } return 0; /* reached only at stdin EOF. */ }
/* Verify the OCSP status of given certificate. Returns * V_OCSP_CERTSTATUS_* result code. */ static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c, SSLSrvConfigRec *sc, server_rec *s, apr_pool_t *pool) { int rc = V_OCSP_CERTSTATUS_GOOD; OCSP_RESPONSE *response = NULL; OCSP_BASICRESP *basicResponse = NULL; OCSP_REQUEST *request = NULL; OCSP_CERTID *certID = NULL; apr_uri_t *ruri; ruri = determine_responder_uri(sc, cert, c, pool); if (!ruri) { return V_OCSP_CERTSTATUS_UNKNOWN; } request = create_request(ctx, cert, &certID, s, pool, sc); if (request) { apr_interval_time_t to = sc->server->ocsp_responder_timeout == UNSET ? apr_time_from_sec(DEFAULT_OCSP_TIMEOUT) : sc->server->ocsp_responder_timeout; response = modssl_dispatch_ocsp_request(ruri, to, request, c, pool); } if (!request || !response) { rc = V_OCSP_CERTSTATUS_UNKNOWN; } if (rc == V_OCSP_CERTSTATUS_GOOD) { int r = OCSP_response_status(response); if (r != OCSP_RESPONSE_STATUS_SUCCESSFUL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01922) "OCSP response not successful: %d", rc); rc = V_OCSP_CERTSTATUS_UNKNOWN; } } if (rc == V_OCSP_CERTSTATUS_GOOD) { basicResponse = OCSP_response_get1_basic(response); if (!basicResponse) { ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(01923) "could not retrieve OCSP basic response"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); rc = V_OCSP_CERTSTATUS_UNKNOWN; } } if (rc == V_OCSP_CERTSTATUS_GOOD && sc->server->ocsp_use_request_nonce != FALSE && OCSP_check_nonce(request, basicResponse) != 1) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01924) "Bad OCSP responder answer (bad nonce)"); rc = V_OCSP_CERTSTATUS_UNKNOWN; } if (rc == V_OCSP_CERTSTATUS_GOOD) { /* TODO: allow flags configuration. */ if (OCSP_basic_verify(basicResponse, NULL, ctx->ctx, 0) != 1) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01925) "failed to verify the OCSP response"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); rc = V_OCSP_CERTSTATUS_UNKNOWN; } } if (rc == V_OCSP_CERTSTATUS_GOOD) { int reason = -1, status; ASN1_GENERALIZEDTIME *thisup = NULL, *nextup = NULL; rc = OCSP_resp_find_status(basicResponse, certID, &status, &reason, NULL, &thisup, &nextup); if (rc != 1) { ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02272) "failed to retrieve OCSP response status"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); rc = V_OCSP_CERTSTATUS_UNKNOWN; } else { rc = status; } /* Check whether the response is inside the defined validity * period; otherwise fail. */ if (rc != V_OCSP_CERTSTATUS_UNKNOWN) { long resptime_skew = sc->server->ocsp_resptime_skew == UNSET ? DEFAULT_OCSP_MAX_SKEW : sc->server->ocsp_resptime_skew; /* oscp_resp_maxage can be passed verbatim - UNSET (-1) means * that responses can be of any age as long as nextup is in the * future. */ int vrc = OCSP_check_validity(thisup, nextup, resptime_skew, sc->server->ocsp_resp_maxage); if (vrc != 1) { ssl_log_cxerror(SSLLOG_MARK, APLOG_ERR, 0, c, cert, APLOGNO(02273) "OCSP response outside validity period"); ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); rc = V_OCSP_CERTSTATUS_UNKNOWN; } } { int level = (status == V_OCSP_CERTSTATUS_GOOD) ? APLOG_INFO : APLOG_ERR; const char *result = status == V_OCSP_CERTSTATUS_GOOD ? "good" : (status == V_OCSP_CERTSTATUS_REVOKED ? "revoked" : "unknown"); ssl_log_cxerror(SSLLOG_MARK, level, 0, c, cert, "OCSP validation completed, " "certificate status: %s (%d, %d)", result, status, reason); } } if (request) OCSP_REQUEST_free(request); if (response) OCSP_RESPONSE_free(response); if (basicResponse) OCSP_BASICRESP_free(basicResponse); /* certID is freed when the request is freed */ return rc; }
/* * Open a new log file, and if successful * also close the old one. * * The timestamp for the calculation of the file * name of the new log file will be the actual millisecond * timestamp, except when a regular rotation based on a time * interval is configured and the previous interval * is over. Then the timestamp is the starting time * of the actual interval. */ static void doRotate(rotate_config_t *config, rotate_status_t *status) { int now = get_now(config); int tLogStart; apr_status_t rv; struct logfile newlog; int thisLogNum = -1; status->rotateReason = ROTATE_NONE; if (config->tRotation) { int tLogEnd; tLogStart = (now / config->tRotation) * config->tRotation; tLogEnd = tLogStart + config->tRotation; /* * Check if rotation was forced and the last rotation * interval is not yet over. Use the value of now instead * of the time interval boundary for the file name then. */ if (tLogStart < status->tLogEnd) { tLogStart = now; } status->tLogEnd = tLogEnd; } else { tLogStart = now; } if (config->use_strftime) { apr_time_t tNow = apr_time_from_sec(tLogStart); apr_time_exp_t e; apr_size_t rs; apr_time_exp_gmt(&e, tNow); apr_strftime(newlog.name, &rs, sizeof(newlog.name), config->szLogRoot, &e); } else { if (config->truncate) { apr_snprintf(newlog.name, sizeof(newlog.name), "%s", config->szLogRoot); } else if (config->num_files > 0) { if (status->fileNum == -1 || status->fileNum == (config->num_files - 1)) { thisLogNum = 0; apr_snprintf(newlog.name, sizeof(newlog.name), "%s", config->szLogRoot); } else { thisLogNum = status->fileNum + 1; apr_snprintf(newlog.name, sizeof(newlog.name), "%s.%d", config->szLogRoot, thisLogNum); } } else { apr_snprintf(newlog.name, sizeof(newlog.name), "%s.%010d", config->szLogRoot, tLogStart); } } apr_pool_create(&newlog.pool, status->pool); if (config->verbose) { fprintf(stderr, "Opening file %s\n", newlog.name); } rv = apr_file_open(&newlog.fd, newlog.name, APR_WRITE | APR_CREATE | APR_APPEND | (config->truncate || (config->num_files > 0 && status->current.fd) ? APR_TRUNCATE : 0), APR_OS_DEFAULT, newlog.pool); if (rv == APR_SUCCESS) { /* Handle post-rotate processing. */ post_rotate(newlog.pool, &newlog, config, status); status->fileNum = thisLogNum; /* Close out old (previously 'current') logfile, if any. */ if (status->current.fd) { close_logfile(config, &status->current); } /* New log file is now 'current'. */ status->current = newlog; } else { char error[120]; apr_strerror(rv, error, sizeof error); /* Uh-oh. Failed to open the new log file. Try to clear * the previous log file, note the lost log entries, * and keep on truckin'. */ if (status->current.fd == NULL) { fprintf(stderr, "Could not open log file '%s' (%s)\n", newlog.name, error); exit(2); } /* Throw away new state; it isn't going to be used. */ apr_pool_destroy(newlog.pool); /* Try to keep this error message constant length * in case it occurs several times. */ apr_snprintf(status->errbuf, sizeof status->errbuf, "Resetting log file due to error opening " "new log file, %10d messages lost: %-25.25s\n", status->nMessCount, error); truncate_and_write_error(status); } status->nMessCount = 0; }
int mq_stream_read_wait(mq_stream_t *mqs) { int err = 0; apr_interval_time_t dt; op_status_t status; //** If 1st time make all the variables if (mqs->mpool == NULL) { apr_pool_create(&mqs->mpool, NULL); apr_thread_mutex_create(&(mqs->lock), APR_THREAD_MUTEX_DEFAULT, mqs->mpool); apr_thread_cond_create(&(mqs->cond), mqs->mpool); } dt = apr_time_from_sec(1); //** Flag the just processed gop to clean up apr_thread_mutex_lock(mqs->lock); log_printf(5, "START msid=%d waiting=%d processed=%d gop_processed=%p\n", mqs->msid, mqs->waiting, mqs->processed, mqs->gop_processed); if (mqs->gop_processed != NULL) mqs->processed = 1; apr_thread_cond_broadcast(mqs->cond); if (mqs->data) { if (mqs->data[MQS_STATE_INDEX] != MQS_MORE) err = 1; } apr_thread_mutex_unlock(mqs->lock); if (mqs->gop_processed != NULL) { gop_waitany(mqs->gop_processed); gop_free(mqs->gop_processed, OP_DESTROY); mqs->gop_processed = NULL; } if (err != 0) { log_printf(2, "ERROR no more data available!\n"); return(-1); } //** Now handle the waiting gop apr_thread_mutex_lock(mqs->lock); log_printf(5, "before loop msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed); while (mqs->waiting == 1) { log_printf(5, "LOOP msid=%d waiting=%d processed=%d\n", mqs->msid, mqs->waiting, mqs->processed); if (gop_will_block(mqs->gop_waiting) == 0) { //** Oops! failed request status = gop_get_status(mqs->gop_waiting); log_printf(2, "msid=%d gid=%d status=%d\n", mqs->msid, gop_id(mqs->gop_waiting), status.op_status); if (status.op_status != OP_STATE_SUCCESS) { mqs->waiting = -3; err = 1; } else { apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt); } } else { apr_thread_cond_timedwait(mqs->cond, mqs->lock, dt); } } if (mqs->waiting == 0) { //** Flag the receiver to accept the data mqs->waiting = -1; apr_thread_cond_broadcast(mqs->cond); //** Let the receiver know we're ready to accept the data //** Wait for the data to be accepted while (mqs->waiting != -2) { apr_thread_cond_wait(mqs->cond, mqs->lock); } } else if (mqs->waiting == -3) { //**error occured err = 1; } apr_thread_mutex_unlock(mqs->lock); //** Flip states mqs->gop_processed = mqs->gop_waiting; mqs->gop_waiting = NULL; //** This shouldn't get triggered but just in case lets throw an error. if ((mqs->gop_processed == NULL) && (mqs->data != NULL)) { if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) { err = 3; log_printf(0, "ERROR: MQS gop processed=waiting=NULL want_more set!!!!!! err=%d\n", err); fprintf(stderr, "ERROR: MQS gop processed=waiting=NULL want_more set!!!!!! err=%d\n", err); } } //** Check if we need to fire off the next request if (mqs->data != NULL) { if ((mqs->data[MQS_STATE_INDEX] == MQS_MORE) && (mqs->want_more == MQS_MORE)) { mq_stream_read_request(mqs); } } log_printf(5, "err=%d\n", err); return(err); }
int main(int argc, char **argv) { int start_option, i, watch, summary, base; rs_mapping_notify_t notify, me; apr_time_t dt; char *config; //printf("argc=%d\n", argc); if (argc < 2) { printf("\n"); printf("lio_rs LIO_COMMON_OPTIONS [-w] [-b2 | -b10] [-s | -f]\n"); lio_print_options(stdout); printf(" -w - Watch for RID configuration changes. Press ^C to exit\n"); printf(" -b2 - Use powers of 2 for units(default)\n"); printf(" -b10 - Use powers of 10 for units\n"); printf(" -s - Print a RID space usage summary\n"); printf(" -f - Print the full RID configuration\n"); return(1); } lio_init(&argc, &argv); watch = 0; summary = 0; base = 1024; i=1; do { start_option = i; if (strcmp(argv[i], "-w") == 0) { //** Watch for any RID changes i++; watch = 1; } else if (strcmp(argv[i], "-s") == 0) { //** Print space summary instead of full conifg i++; summary = 1; } else if (strcmp(argv[i], "-b2") == 0) { //** base-2 units i++; base = 1024; } else if (strcmp(argv[i], "-b10") == 0) { //** base-10 units i++; base = 1000; } } while ((start_option < i) && (i<argc)); //** Make the APR stuff assert_result(apr_pool_create(&mpool, NULL), APR_SUCCESS); apr_thread_mutex_create(&lock, APR_THREAD_MUTEX_DEFAULT, mpool); apr_thread_cond_create(&cond, mpool); //if (watch == 1) { // printf("Sleeping for 60s\n"); fflush(stdout); // sleep(60); // printf("Woken up\n"); fflush(stdout); //} memset(¬ify, 0, sizeof(notify)); notify.lock = lock; notify.cond = cond; me = notify; me.map_version = 1; //** This triggers the initial load rs_register_mapping_updates(lio_gc->rs, ¬ify); dt = apr_time_from_sec(1); do { //** Check for an update apr_thread_mutex_lock(lock); if (watch == 1) apr_thread_cond_timedwait(notify.cond, notify.lock, dt); i = ((me.map_version != notify.map_version) || (me.status_version != notify.status_version)) ? 1 : 0; me = notify; apr_thread_mutex_unlock(lock); if (i != 0) { config = rs_get_rid_config(lio_gc->rs); printf("Map Version: %d Status Version: %d\n", me.map_version, me.status_version); printf("--------------------------------------------------------------------------------------------------\n"); if (config == NULL) { printf("ERROR NULL config!\n"); } else if (summary == 1) { print_rid_summary(config, base); } else { printf("%s", config); } printf("--------------------------------------------------------------------------------------------------\n"); if (config != NULL) free(config); } } while (watch == 1); info_printf(lio_ifd, 5, "BEFORE unregister\n"); tbx_info_flush(lio_ifd); rs_unregister_mapping_updates(lio_gc->rs, ¬ify); info_printf(lio_ifd, 5, "AFTER unregister\n"); tbx_info_flush(lio_ifd); //** Cleanup apr_pool_destroy(mpool); // info_printf(lio_ifd, 5, "AFTER shutdown\n"); tbx_info_flush(lio_ifd); lio_shutdown(); return(0); }
mapcache_http_response *mapcache_core_get_tile(mapcache_context *ctx, mapcache_request_get_tile *req_tile) { int expires = 0; mapcache_http_response *response; int i,is_empty=1 /* response image is initially empty */; char *timestr; mapcache_image *base=NULL; mapcache_image_format *format = NULL; #ifdef DEBUG if(req_tile->ntiles ==0) { ctx->set_error(ctx,500,"BUG: get_tile called with 0 tiles"); return NULL; } #endif response = mapcache_http_response_create(ctx->pool); mapcache_prefetch_tiles(ctx,req_tile->tiles,req_tile->ntiles); if(GC_HAS_ERROR(ctx)) return NULL; /* loop through tiles, and eventually merge them vertically together */ for(i=0; i<req_tile->ntiles; i++) { mapcache_tile *tile = req_tile->tiles[i]; /* shortcut */ if(tile->mtime && (tile->mtime < response->mtime || response->mtime == 0)) response->mtime = tile->mtime; if(tile->expires && (tile->expires < expires || expires == 0)) { expires = tile->expires; } if(tile->nodata) { /* treat the special case where the cache explicitely stated that the tile was empty, and we don't have any vertical merging to do */ if(tile->encoded_data && req_tile->ntiles == 1) { response->data = tile->encoded_data; /* we don't touch is_empty, as we have access to the encoded empty image, but the resulting tile is empty */ } continue; } /* treat the most common case: - we have a single tile request (i.e. isempty is true) - the cache returned the encoded image */ if(is_empty && tile->encoded_data) { response->data = tile->encoded_data; /* just in case we also have the raw image data available, keep a ref to it if we need to merge another tile ontop of it*/ if(tile->raw_image) { base = tile->raw_image; } is_empty = 0; /* we now know we might need to do some vertical merging */ continue; } /* if we're here, either * - we need to merge the current tile onto the previous one(s), or * - we only have the tile's raw data available */ if(!is_empty) { /* we have an existing tile, so we know we need to merge the current one into it */ if(!base) { /* the existing tile has not been decoded yet, but we need the access to the raw pixels*/ base = mapcache_imageio_decode(ctx, response->data); if(!base) return NULL; } response->data = NULL; /* the encoded data is now obsolete, as we will be merging the current tile */ /* we need to access the current tile's pixel data */ if(!tile->raw_image) { tile->raw_image = mapcache_imageio_decode(ctx,tile->encoded_data); if(!tile->raw_image) return NULL; } mapcache_image_merge(ctx, base, tile->raw_image); } else { /* we don't need to merge onto an existing tile and don't have access to the tile's encoded data. * * we don't encode the tile's raw image data just yet because we might need to merge another one on top * of it later. */ base = tile->raw_image; is_empty = 0; } } if(!response->data) { /* we need to encode the raw image data*/ if(base) { if(req_tile->format) { format = req_tile->format; } else { format = req_tile->tiles[0]->tileset->format; if(!format) { format = ctx->config->default_image_format; /* this one is always defined */ } } response->data = format->write(ctx, base, format); if(GC_HAS_ERROR(ctx)) { return NULL; } } else { #ifdef DEBUG if(!is_empty) { ctx->set_error(ctx,500,"BUG: no image data to encode, but tile not marked as empty"); return NULL; } #endif unsigned char empty[5] = {'#',0,0,0,0}; response->data = mapcache_empty_png_decode(ctx,empty,&is_empty); /* is_empty is unchanged and left to 1 */ format = mapcache_configuration_get_image_format(ctx->config,"PNG8"); } } /* compute the content-type */ mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,response->data); if(t == GC_PNG) apr_table_set(response->headers,"Content-Type","image/png"); else if(t == GC_JPEG) apr_table_set(response->headers,"Content-Type","image/jpeg"); /* compute expiry headers */ if(expires) { apr_time_t now = apr_time_now(); apr_time_t additional = apr_time_from_sec(expires); apr_time_t texpires = now + additional; apr_table_set(response->headers, "Cache-Control",apr_psprintf(ctx->pool, "max-age=%d", expires)); timestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN); apr_rfc822_date(timestr, texpires); apr_table_setn(response->headers, "Expires", timestr); } return response; }
void *ongoing_heartbeat_thread(apr_thread_t *th, void *data) { mq_ongoing_t *on = (mq_ongoing_t *)data; apr_time_t timeout = apr_time_make(on->check_interval, 0); op_generic_t *gop; mq_msg_t *msg; ongoing_hb_t *oh; ongoing_table_t *table; apr_hash_index_t *hi, *hit; opque_t *q; char *id; mq_msg_hash_t *remote_hash; apr_time_t now; apr_ssize_t id_len; int n, k; char *remote_host_string; apr_thread_mutex_lock(on->lock); n = 0; do { now = apr_time_now() - apr_time_from_sec(5); //** Give our selves a little buffer log_printf(5, "Loop Start now=" TT "\n", apr_time_now()); q = new_opque(); // opque_start_execution(q); for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) { apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table); k = apr_hash_count(table->table); if (log_level() > 1) { remote_host_string = mq_address_to_string(table->remote_host); log_printf(1, "host=%s count=%d\n", remote_host_string, k); free(remote_host_string); } for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh); log_printf(1, "id=%s now=" TT " next_check=" TT "\n", oh->id, apr_time_sec(apr_time_now()), apr_time_sec(oh->next_check)); if (now > oh->next_check) { log_printf(1, "id=%s sending HEARTBEAT EXEC SUBMIT nows=" TT " hb=%d\n", oh->id, apr_time_sec(apr_time_now()), oh->heartbeat); flush_log(); //** Form the message msg = mq_make_exec_core_msg(table->remote_host, 1); mq_msg_append_mem(msg, ONGOING_KEY, ONGOING_SIZE, MQF_MSG_KEEP_DATA); mq_msg_append_mem(msg, oh->id, oh->id_len, MQF_MSG_KEEP_DATA); mq_msg_append_mem(msg, NULL, 0, MQF_MSG_KEEP_DATA); //** Make the gop gop = new_mq_op(on->mqc, msg, ongoing_response_status, NULL, NULL, oh->heartbeat); gop_set_private(gop, table); opque_add(q, gop); oh->in_progress = 1; //** Flag it as in progress so it doesn't get deleted behind the scenes } } } log_printf(5, "Loop end now=" TT "\n", apr_time_now()); //** Wait for it to complete apr_thread_mutex_unlock(on->lock); opque_waitall(q); apr_thread_mutex_lock(on->lock); //** Dec the counters while ((gop = opque_waitany(q)) != NULL) { log_printf(0, "gid=%d gotone status=%d now=" TT "\n", gop_id(gop), (gop_get_status(gop)).op_status, apr_time_sec(apr_time_now())); table = gop_get_private(gop); table->count--; //** Update the next check for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh); oh->next_check = apr_time_now() + apr_time_from_sec(oh->heartbeat); //** Check if we get rid of it oh->in_progress = 0; if (oh->count <= 0) { //** Need to delete it apr_hash_set(table->table, id, id_len, NULL); free(oh->id); free(oh); } } gop_free(gop, OP_DESTROY); } opque_free(q, OP_DESTROY); now = apr_time_now(); log_printf(2, "sleeping %d now=" TT "\n", on->check_interval, now); //** Sleep until time for the next heartbeat or time to exit if (on->shutdown == 0) apr_thread_cond_timedwait(on->cond, on->lock, timeout); n = on->shutdown; now = apr_time_now() - now; log_printf(2, "main loop bottom n=%d dt=" TT " sec=" TT "\n", n, now, apr_time_sec(now)); } while (n == 0); log_printf(2, "CLEANUP\n"); for (hit = apr_hash_first(NULL, on->table); hit != NULL; hit = apr_hash_next(hit)) { apr_hash_this(hit, (const void **)&remote_hash, &id_len, (void **)&table); for (hi = apr_hash_first(NULL, table->table); hi != NULL; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&id, &id_len, (void **)&oh); apr_hash_set(table->table, id, id_len, NULL); free(oh->id); free(oh); } apr_hash_set(on->table, &(table->remote_host_hash), sizeof(mq_msg_hash_t), NULL); mq_msg_destroy(table->remote_host); free(table); } log_printf(2, "EXITING\n"); apr_thread_mutex_unlock(on->lock); return(NULL); }
mapcache_http_response *mapcache_core_get_map(mapcache_context *ctx, mapcache_request_get_map *req_map) { mapcache_image_format *format = NULL; mapcache_http_response *response; mapcache_map *basemap = NULL; char *timestr; #ifdef DEBUG if(req_map->nmaps ==0) { ctx->set_error(ctx,500,"BUG: get_map called with 0 maps"); return NULL; } #endif if(req_map->getmap_strategy == MAPCACHE_GETMAP_ERROR) { ctx->set_error(ctx, 404, "full wms support disabled"); return NULL; } format = NULL; response = mapcache_http_response_create(ctx->pool); if(req_map->getmap_strategy == MAPCACHE_GETMAP_ASSEMBLE) { basemap = mapcache_assemble_maps(ctx, req_map->maps, req_map->nmaps, req_map->resample_mode); if(GC_HAS_ERROR(ctx)) return NULL; } else if(!ctx->config->non_blocking && req_map->getmap_strategy == MAPCACHE_GETMAP_FORWARD) { int i; basemap = req_map->maps[0]; for(i=0; i<req_map->nmaps; i++) { if(!req_map->maps[i]->tileset->source) { ctx->set_error(ctx,404,"cannot forward request for tileset %s: no source configured", req_map->maps[i]->tileset->name); return NULL; } } basemap->tileset->source->render_map(ctx, basemap); if(GC_HAS_ERROR(ctx)) return NULL; if(req_map->nmaps>1) { if(!basemap->raw_image) { basemap->raw_image = mapcache_imageio_decode(ctx,basemap->encoded_data); if(GC_HAS_ERROR(ctx)) return NULL; } for(i=1; i<req_map->nmaps; i++) { mapcache_map *overlaymap = req_map->maps[i]; overlaymap->tileset->source->render_map(ctx, overlaymap); if(GC_HAS_ERROR(ctx)) return NULL; if(!overlaymap->raw_image) { overlaymap->raw_image = mapcache_imageio_decode(ctx,overlaymap->encoded_data); if(GC_HAS_ERROR(ctx)) return NULL; } if(GC_HAS_ERROR(ctx)) return NULL; mapcache_image_merge(ctx,basemap->raw_image,overlaymap->raw_image); if(GC_HAS_ERROR(ctx)) return NULL; if(!basemap->expires || overlaymap->expires<basemap->expires) basemap->expires = overlaymap->expires; } } } else { ctx->set_error(ctx,400,"failed getmap, readonly mode"); return NULL; } if(basemap->raw_image) { format = req_map->getmap_format; /* always defined, defaults to JPEG */ response->data = format->write(ctx,basemap->raw_image,format); if(GC_HAS_ERROR(ctx)) { return NULL; } } else { /* this case happens when we have a forward strategy for a single tileset */ #ifdef DEBUG if(!basemap->encoded_data) { ctx->set_error(ctx,500,"###BUG### core_get_map failed with null encoded_data"); return NULL; } #endif response->data = basemap->encoded_data; } /* compute the content-type */ if(format && format->mime_type) { apr_table_set(response->headers,"Content-Type",format->mime_type); } else { mapcache_image_format_type t = mapcache_imageio_header_sniff(ctx,response->data); if(t == GC_PNG) apr_table_set(response->headers,"Content-Type","image/png"); else if(t == GC_JPEG) apr_table_set(response->headers,"Content-Type","image/jpeg"); } /* compute expiry headers */ if(basemap->expires) { apr_time_t now = apr_time_now(); apr_time_t additional = apr_time_from_sec(basemap->expires); apr_time_t texpires = now + additional; apr_table_set(response->headers, "Cache-Control", apr_psprintf(ctx->pool, "max-age=%d", basemap->expires)); timestr = apr_palloc(ctx->pool, APR_RFC822_DATE_LEN); apr_rfc822_date(timestr, texpires); apr_table_setn(response->headers, "Expires", timestr); } response->mtime = basemap->mtime; return response; }
/* Implements svn_config_enumerator2_t. */ static svn_boolean_t add_memcache_server(const char *name, const char *value, void *baton, apr_pool_t *pool) { struct ams_baton *b = baton; char *host, *scope; apr_port_t port; apr_status_t apr_err; apr_memcache_server_t *server; apr_err = apr_parse_addr_port(&host, &scope, &port, value, pool); if (apr_err != APR_SUCCESS) { b->err = svn_error_wrap_apr(apr_err, _("Error parsing memcache server '%s'"), name); return FALSE; } if (scope) { b->err = svn_error_createf(SVN_ERR_BAD_SERVER_SPECIFICATION, NULL, _("Scope not allowed in memcache server " "'%s'"), name); return FALSE; } if (!host || !port) { b->err = svn_error_createf(SVN_ERR_BAD_SERVER_SPECIFICATION, NULL, _("Must specify host and port for memcache " "server '%s'"), name); return FALSE; } /* Note: the four numbers here are only relevant when an apr_memcache_t is being shared by multiple threads. */ apr_err = apr_memcache_server_create(b->memcache_pool, host, port, 0, /* min connections */ 5, /* soft max connections */ 10, /* hard max connections */ /* time to live (in microseconds) */ apr_time_from_sec(50), &server); if (apr_err != APR_SUCCESS) { b->err = svn_error_wrap_apr(apr_err, _("Unknown error creating memcache server")); return FALSE; } apr_err = apr_memcache_add_server(b->memcache, server); if (apr_err != APR_SUCCESS) { b->err = svn_error_wrap_apr(apr_err, _("Unknown error adding server to memcache")); return FALSE; } return TRUE; }
static apr_status_t rfc1413_connect(apr_socket_t **newsock, conn_rec *conn, server_rec *srv) { apr_status_t rv; apr_sockaddr_t *localsa, *destsa; if ((rv = apr_sockaddr_info_get(&localsa, conn->local_ip, APR_UNSPEC, 0, /* ephemeral port */ 0, conn->pool)) != APR_SUCCESS) { /* This should not fail since we have a numeric address string * as the host. */ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv, "rfc1413: apr_sockaddr_info_get(%s) failed", conn->local_ip); return rv; } if ((rv = apr_sockaddr_info_get(&destsa, conn->remote_ip, localsa->family, /* has to match */ RFC1413_PORT, 0, conn->pool)) != APR_SUCCESS) { /* This should not fail since we have a numeric address string * as the host. */ ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv, "rfc1413: apr_sockaddr_info_get(%s) failed", conn->remote_ip); return rv; } if ((rv = apr_socket_create(newsock, localsa->family, /* has to match */ SOCK_STREAM, conn->pool)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv, "rfc1413: error creating query socket"); return rv; } if ((rv = apr_socket_timeout_set(*newsock, apr_time_from_sec(ap_rfc1413_timeout))) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv, "rfc1413: error setting query socket timeout"); apr_socket_close(*newsock); return rv; } /* * Bind the local and remote ends of the query socket to the same * IP addresses as the connection under investigation. We go * through all this trouble because the local or remote system * might have more than one network address. The RFC1413 etc. * client sends only port numbers; the server takes the IP * addresses from the query socket. */ if ((rv = apr_bind(*newsock, localsa)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_CRIT, rv, srv, "rfc1413: Error binding query socket to local port"); apr_socket_close(*newsock); return rv; } /* * errors from connect usually imply the remote machine doesn't support * the service; don't log such an error */ if ((rv = apr_connect(*newsock, destsa)) != APR_SUCCESS) { apr_socket_close(*newsock); return rv; } return APR_SUCCESS; }
/* This function connects to the server and sends enough data to * ensure the child wakes up and processes a new connection. This * permits the MPM to skip the poll when there is only one listening * socket, because it provides a alternate way to unblock an accept() * when the pod is used. */ static apr_status_t dummy_connection(ap_pod_t *pod) { const char *data; apr_status_t rv; apr_socket_t *sock; apr_pool_t *p; apr_size_t len; ap_listen_rec *lp; /* create a temporary pool for the socket. pconf stays around too long */ rv = apr_pool_create(&p, pod->p); if (rv != APR_SUCCESS) { return rv; } /* If possible, find a listener which is configured for * plain-HTTP, not SSL; using an SSL port would either be * expensive to do correctly (performing a complete SSL handshake) * or cause log spam by doing incorrectly (simply sending EOF). */ lp = ap_listeners; while (lp && lp->protocol && strcasecmp(lp->protocol, "http") != 0) { lp = lp->next; } if (!lp) { lp = ap_listeners; } rv = apr_socket_create(&sock, lp->bind_addr->family, SOCK_STREAM, 0, p); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00054) "get socket to connect to listener"); apr_pool_destroy(p); return rv; } /* on some platforms (e.g., FreeBSD), the kernel won't accept many * queued connections before it starts blocking local connects... * we need to keep from blocking too long and instead return an error, * because the MPM won't want to hold up a graceful restart for a * long time */ rv = apr_socket_timeout_set(sock, apr_time_from_sec(3)); if (rv != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, ap_server_conf, APLOGNO(00055) "set timeout on socket to connect to listener"); apr_socket_close(sock); apr_pool_destroy(p); return rv; } rv = apr_socket_connect(sock, lp->bind_addr); if (rv != APR_SUCCESS) { int log_level = APLOG_WARNING; if (APR_STATUS_IS_TIMEUP(rv)) { /* probably some server processes bailed out already and there * is nobody around to call accept and clear out the kernel * connection queue; usually this is not worth logging */ log_level = APLOG_DEBUG; } ap_log_error(APLOG_MARK, log_level, rv, ap_server_conf, APLOGNO(00056) "connect to listener on %pI", lp->bind_addr); apr_pool_destroy(p); return rv; } if (lp->protocol && strcasecmp(lp->protocol, "https") == 0) { /* Send a TLS 1.0 close_notify alert. This is perhaps the * "least wrong" way to open and cleanly terminate an SSL * connection. It should "work" without noisy error logs if * the server actually expects SSLv3/TLSv1. With * SSLv23_server_method() OpenSSL's SSL_accept() fails * ungracefully on receipt of this message, since it requires * an 11-byte ClientHello message and this is too short. */ static const unsigned char tls10_close_notify[7] = { '\x15', /* TLSPlainText.type = Alert (21) */ '\x03', '\x01', /* TLSPlainText.version = {3, 1} */ '\x00', '\x02', /* TLSPlainText.length = 2 */ '\x01', /* Alert.level = warning (1) */ '\x00' /* Alert.description = close_notify (0) */ }; data = (const char *)tls10_close_notify; len = sizeof(tls10_close_notify); } else /* ... XXX other request types here? */ { /* Create an HTTP request string. We include a User-Agent so * that adminstrators can track down the cause of the * odd-looking requests in their logs. A complete request is * used since kernel-level filtering may require that much * data before returning from accept(). */ data = apr_pstrcat(p, "OPTIONS * HTTP/1.0\r\nUser-Agent: ", ap_get_server_description(), " (internal dummy connection)\r\n\r\n", NULL); len = strlen(data); } apr_socket_send(sock, data, &len); apr_socket_close(sock); apr_pool_destroy(p); return rv; }
int main ( int argc, char *argv[] ) { int rc; struct stat struct_stat; pthread_t pid; pthread_attr_t attr; int i, num_sources; uid_t gmetad_uid; mode_t rrd_umask; char * gmetad_username; struct passwd *pw; gmetad_config_t *c = &gmetad_config; apr_interval_time_t sleep_time; apr_time_t last_metadata; double random_sleep_factor; unsigned int rand_seed; rc = apr_initialize(); if (rc != APR_SUCCESS) { return -1; } /* create a memory pool. */ apr_pool_create(&global_context, NULL); /* Ignore SIGPIPE */ signal( SIGPIPE, SIG_IGN ); initialize_scoreboard(); /* Mark the time this gmetad started */ started = apr_time_now(); if (cmdline_parser(argc, argv, &args_info) != 0) err_quit("command-line parser error"); num_sources = number_of_datasources( args_info.conf_arg ); if(!num_sources) { err_quit("%s doesn't have any data sources specified", args_info.conf_arg); } memset(&root, 0, sizeof(root)); root.id = ROOT_NODE; /* Get the real number of data sources later */ sources = hash_create( num_sources + 10 ); if (! sources ) { err_quit("Unable to create sources hash\n"); } root.authority = hash_create( num_sources + 10 ); if (!root.authority) { err_quit("Unable to create root authority (our grids and clusters) hash\n"); } root.metric_summary = hash_create (DEFAULT_METRICSIZE); if (!root.metric_summary) { err_quit("Unable to create root summary hash"); } parse_config_file ( args_info.conf_arg ); /* If given, use command line directives over config file ones. */ if (args_info.debug_given) { c->debug_level = args_info.debug_arg; } debug_level = c->debug_level; set_debug_msg_level(debug_level); /* Setup our default authority pointer if the conf file hasnt yet. * Done in the style of hash node strings. */ if (!root.stringslen) { gethostname(hostname, HOSTNAMESZ); root.authority_ptr = 0; sprintf(root.strings, "http://%s/ganglia/", hostname); root.stringslen += strlen(root.strings) + 1; } rand_seed = apr_time_now() * (int)pthread_self(); for(i = 0; i < root.stringslen; rand_seed = rand_seed * root.strings[i++]); /* Debug level 1 is error output only, and no daemonizing. */ if (!debug_level) { rrd_umask = c->umask; daemon_init (argv[0], 0, rrd_umask); } if (args_info.pid_file_given) { update_pidfile (args_info.pid_file_arg); } /* The rrd_rootdir must be writable by the gmetad process */ if( c->should_setuid ) { if(! (pw = getpwnam(c->setuid_username))) { err_sys("Getpwnam error"); } gmetad_uid = pw->pw_uid; gmetad_username = c->setuid_username; } else { gmetad_uid = getuid(); if(! (pw = getpwuid(gmetad_uid))) { err_sys("Getpwnam error"); } gmetad_username = strdup(pw->pw_name); } debug_msg("Going to run as user %s", gmetad_username); if( c->should_setuid ) { become_a_nobody(c->setuid_username); } if( c->write_rrds ) { if( stat( c->rrd_rootdir, &struct_stat ) ) { err_sys("Please make sure that %s exists", c->rrd_rootdir); } if ( struct_stat.st_uid != gmetad_uid ) { err_quit("Please make sure that %s is owned by %s", c->rrd_rootdir, gmetad_username); } if (! (struct_stat.st_mode & S_IWUSR) ) { err_quit("Please make sure %s has WRITE permission for %s", gmetad_username, c->rrd_rootdir); } } if(debug_level) { fprintf(stderr,"Sources are ...\n"); hash_foreach( sources, print_sources, NULL); } #ifdef WITH_MEMCACHED if (c->memcached_parameters != NULL) { memcached_connection_pool = memcached_pool(c->memcached_parameters, strlen(c->memcached_parameters)); } #endif /* WITH_MEMCACHED */ server_socket = g_tcp_socket_server_new( c->xml_port ); if (server_socket == NULL) { err_quit("tcp_listen() on xml_port failed"); } debug_msg("xml listening on port %d", c->xml_port); interactive_socket = g_tcp_socket_server_new( c->interactive_port ); if (interactive_socket == NULL) { err_quit("tcp_listen() on interactive_port failed"); } debug_msg("interactive xml listening on port %d", c->interactive_port); /* Forward metrics to Graphite using carbon protocol */ if (c->carbon_server != NULL) { if (!strcmp(c->carbon_protocol, "udp")) { carbon_udp_socket = init_carbon_udp_socket (c->carbon_server, c->carbon_port); if (carbon_udp_socket == NULL) err_quit("carbon %s socket failed for %s:%d", c->carbon_protocol, c->carbon_server, c->carbon_port); } debug_msg("carbon forwarding ready to send via %s to %s:%d", c->carbon_protocol, c->carbon_server, c->carbon_port); } #ifdef WITH_RIEMANN if (c->riemann_server !=NULL) { if (!strcmp(c->riemann_protocol, "udp")) { riemann_udp_socket = init_riemann_udp_socket (c->riemann_server, c->riemann_port); if (riemann_udp_socket == NULL) err_quit("[riemann] %s socket failed for %s:%d", c->riemann_protocol, c->riemann_server, c->riemann_port); } else { err_quit("[riemann] TCP transport not supported yet."); } debug_msg("[riemann] ready to forward metrics via %s to %s:%d", c->riemann_protocol, c->riemann_server, c->riemann_port); } #endif /* WITH_RIEMANN */ /* initialize summary mutex */ root.sum_finished = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); pthread_mutex_init(root.sum_finished, NULL); pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); /* Spin off the non-interactive server threads. (Half as many as interactive). */ for (i=0; i < c->server_threads/2; i++) pthread_create(&pid, &attr, server_thread, (void*) 0); /* Spin off the interactive server threads. */ for (i=0; i < c->server_threads; i++) pthread_create(&pid, &attr, server_thread, (void*) 1); hash_foreach( sources, spin_off_the_data_threads, NULL ); /* A thread to cleanup old metrics and hosts */ pthread_create(&pid, &attr, cleanup_thread, (void *) NULL); debug_msg("cleanup thread has been started"); /* Meta data */ last_metadata = 0; for(;;) { /* Do at a random interval, between (shortest_step/2) +/- METADATA_SLEEP_RANDOMIZE percent */ random_sleep_factor = (1 + (METADATA_SLEEP_RANDOMIZE / 50.0) * ((rand_r(&rand_seed) - RAND_MAX/2)/(float)RAND_MAX)); sleep_time = random_sleep_factor * apr_time_from_sec(c->shortest_step) / 2; /* Make sure the sleep time is at least 1 second */ if(apr_time_sec(apr_time_now() + sleep_time) < (METADATA_MINIMUM_SLEEP + apr_time_sec(apr_time_now()))) sleep_time += apr_time_from_sec(METADATA_MINIMUM_SLEEP); apr_sleep(sleep_time); /* Need to be sure root is locked while doing summary */ pthread_mutex_lock(root.sum_finished); /* Flush the old values */ hash_foreach(root.metric_summary, zero_out_summary, NULL); root.hosts_up = 0; root.hosts_down = 0; /* Sum the new values */ hash_foreach(root.authority, do_root_summary, NULL ); /* summary completed */ pthread_mutex_unlock(root.sum_finished); /* Save them to RRD */ hash_foreach(root.metric_summary, write_root_summary, NULL); /* Remember our last run */ last_metadata = apr_time_now(); } apr_pool_destroy(global_context); apr_terminate(); return 0; }
// Generate the actual cookie void make_cookie(request_rec *r, char uid[], char cur_uid[], int use_dnt_expires) { // configuration cookietrack_settings_rec *dcfg; dcfg = ap_get_module_config(r->per_dir_config, &cookietrack_module); /* 1024 == hardcoded constant */ char cookiebuf[1024]; char *new_cookie; const char *rname = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME, NULL); /* XXX: hmm, this should really tie in with mod_unique_id */ apr_snprintf(cookiebuf, sizeof(cookiebuf), "%s", uid ); if (dcfg->expires) { /* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */ new_cookie = apr_psprintf(r->pool, "%s=%s; path=/", dcfg->cookie_name, cookiebuf); if ((dcfg->style == CT_UNSET) || (dcfg->style == CT_NETSCAPE)) { apr_time_exp_t tms; apr_time_exp_gmt(&tms, r->request_time + apr_time_from_sec(dcfg->expires)); // this sets a fixed expires in the future if( use_dnt_expires ) { new_cookie = apr_psprintf( r->pool, "%s; expires=%s", new_cookie, dcfg->dnt_expires ); // use the dynamic one } else { new_cookie = apr_psprintf( r->pool, "%s; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", new_cookie, apr_day_snames[tms.tm_wday], tms.tm_mday, apr_month_snames[tms.tm_mon], tms.tm_year % 100, tms.tm_hour, tms.tm_min, tms.tm_sec ); } } else { int expires = 0; // use a static expires date in the future if( use_dnt_expires ) { time_t t; time( &t ); expires = dcfg->dnt_max_age - t; // use the dynamic one } else { expires = dcfg->expires; } _DEBUG && fprintf( stderr, "Expires = %d\n", expires ); new_cookie = apr_psprintf( r->pool, "%s; max-age=%d", new_cookie, expires ); } } else { new_cookie = apr_psprintf(r->pool, "%s=%s; path=/", dcfg->cookie_name, cookiebuf); } if (dcfg->cookie_domain != NULL) { new_cookie = apr_pstrcat(r->pool, new_cookie, "; domain=", dcfg->cookie_domain, (dcfg->style == CT_COOKIE2 ? "; version=1" : ""), NULL); } // r->err_headers_out also honors non-2xx responses and // internal redirects. See the patch here: // http://svn.apache.org/viewvc?view=revision&revision=1154620 apr_table_addn( r->err_headers_out, (dcfg->style == CT_COOKIE2 ? "Set-Cookie2" : "Set-Cookie"), new_cookie ); // we also set it on the INCOMING cookie header, so the app can // Just Use It without worrying. Only do so if we don't already // have an incoming cookie value, or it will send 2 cookies with // the same name, with both the old and new value :( if( !cur_uid ) { apr_table_addn( r->headers_in, "Cookie", new_cookie ); } // Set headers? We set both incoming AND outgoing: if( dcfg->send_header ) { // incoming apr_table_addn( r->headers_in, dcfg->header_name, apr_pstrdup(r->pool, uid) ); // outgoing apr_table_addn( r->err_headers_out, dcfg->header_name, apr_pstrdup(r->pool, uid) ); } // set a note, so we can capture it in the logs // this expects chars, and apr_pstrdup will make sure any char stays // in scope for the function. If not, it ends up being empty. apr_table_setn( r->notes, dcfg->note_name, apr_pstrdup(r->pool, uid) ); }