static int upload_progress_handle_request(request_rec *r) { /**/up_log(APLOG_MARK, APLOG_DEBUG, 0, r->server, "upload_progress_handle_request()"); DirConfig* dir = (DirConfig*)ap_get_module_config(r->per_dir_config, &upload_progress_module); ServerConfig *config = get_server_config(r->server); if (dir && dir->track_enabled > 0) { if (r->method_number == M_POST) { int param_error; const char* id = get_progress_id(r, ¶m_error); if (id) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Upload id='%s' in trackable location: %s.", id, r->uri); CACHE_LOCK(); clean_old_connections(r); upload_progress_node_t *node = find_node(r, id); if (node == NULL) { node = insert_node(r, id); if (node) up_log(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Added upload with id='%s' to list.", id); } else if (node->done) { fill_new_upload_node_data(node, r); up_log(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Reused existing node with id='%s'.", id); } else { node = NULL; ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server, "Upload Progress: Upload with id='%s' already exists, ignoring.", id); } if (node) { upload_progress_context_t *ctx = (upload_progress_context_t*)apr_pcalloc(r->pool, sizeof(upload_progress_context_t)); ctx->node = node; ctx->r = r; apr_pool_cleanup_register(r->pool, ctx, upload_progress_cleanup, apr_pool_cleanup_null); ap_add_input_filter("UPLOAD_PROGRESS", NULL, r, r->connection); } CACHE_UNLOCK(); } else if (param_error < 0) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Upload with invalid ID in trackable location: %s.", r->uri); /* return HTTP_BAD_REQUEST; return HTTP_NOT_FOUND; */ } else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Upload without ID in trackable location: %s.", r->uri); } } } return DECLINED; }
static void clean_old_connections(request_rec *r) { upload_progress_node_t *prev = NULL; ServerConfig *config = get_server_config(r); CACHE_LOCK(); upload_progress_node_t *node = fetch_first_node(config); while(node != NULL) { if(time(NULL) > node->expires && node->done == 1 && node->expires != -1) { /*clean*/ if(prev == NULL) { /* head */ upload_progress_cache_t *cache = fetch_cache(config); cache->head = fetch_node(config, node->next); cache_free(config, node->key); cache_free(config, node); node = cache->head; continue; } else { prev->next = node->next; cache_free(config, node->key); cache_free(config, node); node = prev; continue; } } prev = node; node = fetch_node(config, node->next); } CACHE_UNLOCK(); }
static int upload_progress_handle_request(request_rec *r) { DirConfig* dir = (DirConfig*)ap_get_module_config(r->per_dir_config, &upload_progress_module); ServerConfig *config = get_server_config(r); if(dir->track_enabled) { if(r->method_number == M_POST) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Upload in trackable location: %s.", r->uri); const char* id = get_progress_id(r); if(id != NULL) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Progress id found: %s.", id); CACHE_LOCK(); upload_progress_node_t *node = find_node(r, id); CACHE_UNLOCK(); if(node == NULL) { add_upload_to_track(r, id); ap_add_input_filter("UPLOAD_PROGRESS", NULL, r, r->connection); } else { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Node with id '%s' already exists.", id); } return DECLINED; } } } return DECLINED; }
static const char* upload_progress_shared_memory_size_cmd(cmd_parms *cmd, void *dummy, const char *arg) { /**/up_log(APLOG_MARK, APLOG_DEBUG, 0, global_server, "upload_progress_shared_memory_size_cmd()"); ServerConfig *config = get_server_config(cmd->server); long long int n = atoi(arg); if (n <= 0) { return "UploadProgressSharedMemorySize should be positive"; } config->cache_bytes = (apr_size_t)n; return NULL; }
int add_upload_to_track(request_rec* r, const char* key) { ServerConfig *config = get_server_config(r); upload_progress_node_t* node; clean_old_connections(r); CACHE_LOCK(); node = find_node(r, key); if(node == NULL) { node = insert_node(r, key); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Upload Progress: Added upload with id=%s to list.", key); upload_progress_context_t *ctx = (upload_progress_context_t*)apr_pcalloc(r->pool, sizeof(upload_progress_context_t)); ctx->node = node; ctx->r = r; CACHE_UNLOCK(); apr_pool_cleanup_register(r->pool, ctx, upload_progress_cleanup, apr_pool_cleanup_null); return OK; } CACHE_UNLOCK(); return OK; }
static int track_upload_progress(ap_filter_t *f, apr_bucket_brigade *bb, ap_input_mode_t mode, apr_read_type_e block, apr_off_t readbytes) { apr_status_t rv; upload_progress_node_t *node; ServerConfig* config = get_server_config(f->r); if ((rv = ap_get_brigade(f->next, bb, mode, block, readbytes)) != APR_SUCCESS) { return rv; } apr_off_t length; apr_brigade_length(bb, 1, &length); const char* id = get_progress_id(f->r); if(id == NULL) return APR_SUCCESS; CACHE_LOCK(); node = find_node(f->r, id); CACHE_UNLOCK(); if(node == NULL) { return APR_SUCCESS; } else { CACHE_LOCK(); node->received += (int)length; int upload_time = time(NULL) - node->started_at; if(upload_time > 0) { node->speed = (int)(node->received / upload_time); } CACHE_UNLOCK(); } return APR_SUCCESS; }