// Multicast packet. static apr_status_t multicast_packet(request_rec* rec, multicast_conf* conf, const char* _msg) { int r, s = socket(AF_INET, SOCK_DGRAM, 0); char* msg = unescape_specialchars(rec->pool, _msg); AP_LOG_DEBUG(rec, "unescaped string: %s", msg); r = setsockopt(s, SOL_IP, IP_MULTICAST_IF, conf->multicast_interface.addr, conf->multicast_interface.len); if(r!=0) { r = errno; AP_LOG_ERR(rec, "setsockopt() failed - %s(%d)", strerror(r), r); goto FINALLY; } r = connect(s, conf->multicast_address.addr, conf->multicast_address.len); if(r!=0) { r = errno; AP_LOG_ERR(rec, "connect() failed - %s(%d)", strerror(r), r); goto FINALLY; } r = send(s, msg, strlen(msg), 0); r = (r>=0)? APR_SUCCESS: errno; FINALLY: if(s>=0) { shutdown(s, SHUT_RDWR); close(s); } return r; }
// // Output filter. // static apr_status_t resize_output_filter(ap_filter_t* f, apr_bucket_brigade* in_bb) { request_rec* rec =f->r; resize_conf* conf = (resize_conf*)ap_get_module_config(rec->per_dir_config, &resizeimage_module); const char* content_type, *target_type = "JPEG"; const char* image_url, *resize_param, *image_hash=NULL; Magick::Blob blob; char* vlob = NULL; size_t vlob_length = 0; int cache_hit = FALSE; AP_LOG_VERBOSE(rec, "Incoming %s.", __FUNCTION__); // Pass thru by request types. if(rec->status!=HTTP_OK || rec->main!=NULL || rec->header_only || (rec->handler!= NULL && strcmp(rec->handler, "default-handler") == 0)) goto PASS_THRU; AP_LOG_VERBOSE(rec, "-- Checking responce headers."); // Obtain and erase x-resize-image header or pass through. image_url = get_and_unset_header(rec->headers_out, X_RESIZE); if(image_url== NULL || image_url[0]=='\0') { image_url = get_and_unset_header(rec->err_headers_out, X_RESIZE); } if(image_url==NULL || image_url[0]=='\0') goto PASS_THRU; // Check content-type content_type = rec->content_type; if(content_type) { if(strcasecmp(content_type, "image/jpeg")==0) { target_type = "JPEG"; } else if(strcasecmp(content_type, "image/png")==0) { target_type = "PNG"; } else if(strcasecmp(content_type, "image/gif")==0) { target_type = "GIF"; } else goto PASS_THRU; } // Resize parameter resize_param = get_and_unset_header(rec->headers_out, X_RESIZE_PARAM); if(resize_param==NULL || resize_param[0]=='\0') { resize_param = get_and_unset_header(rec->err_headers_out, X_RESIZE_PARAM); } if(resize_param[0]=='\0') resize_param = NULL; // Image hash image_hash = get_and_unset_header(rec->headers_out, X_RESIZE_HASH); if(image_hash==NULL || image_hash[0]=='\0') { image_hash = get_and_unset_header(rec->err_headers_out, X_RESIZE_HASH); } // Open image and resize. AP_LOG_INFO(rec, "URL: %s, %s => %s (%s)", image_url, content_type, resize_param, image_hash); if(image_hash) { // Try memcached... image_hash = apr_psprintf(rec->pool, "%s:%s:%s", image_hash, target_type, resize_param); memcached_return r; uint32_t flags; vlob = memcached_get(conf->memc, image_hash, strlen(image_hash), &vlob_length, &flags, &r); if(r==MEMCACHED_SUCCESS) { AP_LOG_DEBUG(rec, "Restored from memcached: %s, len=%d", image_hash, vlob_length); cache_hit = TRUE; goto WRITE_DATA; } else { AP_LOG_DEBUG(rec, "Can't restore from memcached: %s - %s(%d)", image_hash, memcached_strerror(conf->memc, r), r); } } // Reszize try { Magick::Image image; image.read(image_url); if(resize_param) image.zoom(resize_param); image.magick(target_type); image.quality(conf->jpeg_quality); image.write(&blob); vlob = (char*)blob.data(); vlob_length = blob.length(); } catch(Magick::Exception& err) { AP_LOG_ERR(rec, __FILE__ ": Magick failed: %s", err.what()); goto PASS_THRU; } if(image_hash) { // Store to memcached... memcached_return r = memcached_set(conf->memc, image_hash, strlen(image_hash), vlob, vlob_length, conf->expire, 0); if(r==MEMCACHED_SUCCESS) { AP_LOG_DEBUG(rec, "Stored to memcached: %s(len=%d)", image_hash, vlob_length); } else { AP_LOG_DEBUG(rec, "Can't store from memcached: %s(len=%d) - %s(%d)", image_hash, vlob_length,memcached_strerror(conf->memc, r), r); } } WRITE_DATA: AP_LOG_VERBOSE(rec, "-- Creating resize buckets."); // Drop all content and headers related. while(!APR_BRIGADE_EMPTY(in_bb)) { apr_bucket* b = APR_BRIGADE_FIRST(in_bb); apr_bucket_delete(b); } rec->eos_sent = 0; rec->clength = 0; unset_header(rec, "Content-Length"); unset_header(rec, "Content-Encoding"); unset_header(rec, "Last-Modified"); unset_header(rec, "ETag"); // Start resize bucket. { apr_off_t remain = vlob_length, offset = 0; while(remain>0) { apr_off_t bs = (remain<AP_MAX_SENDFILE)? remain: AP_MAX_SENDFILE; char* heap = (char*)malloc(bs); memcpy(heap, vlob+offset, bs); apr_bucket* b = apr_bucket_heap_create(heap, bs, free, in_bb-> bucket_alloc); APR_BRIGADE_INSERT_TAIL(in_bb, b); remain -= bs; offset += bs; } APR_BRIGADE_INSERT_TAIL(in_bb, apr_bucket_eos_create(in_bb->bucket_alloc)); ap_set_content_length(rec, vlob_length); if(cache_hit) free(vlob); } AP_LOG_VERBOSE(rec, "-- Create done."); PASS_THRU: AP_LOG_VERBOSE(rec, "-- Filter done."); ap_remove_output_filter(f); return ap_pass_brigade(f->next, in_bb); }
// // Output filter. // static apr_status_t reproxy_output_filter(ap_filter_t* f, apr_bucket_brigade* in_bb) { request_rec* rec =f->r; const char* reproxy_url; AP_LOG_VERBOSE(rec, "Incoming %s.", __FUNCTION__); // Pass thru by request types. if(rec->status!=HTTP_OK || rec->main!=NULL || rec->header_only || (rec->handler!= NULL && strcmp(rec->handler, "default-handler") == 0)) goto PASS_THRU; AP_LOG_VERBOSE(rec, "-- Checking responce headers."); // Obtain and erase x-reproxy-url header or pass through. reproxy_url = get_and_unset_header(rec->headers_out, X_REPROXY); if(reproxy_url== NULL || reproxy_url[0]=='\0') { reproxy_url = get_and_unset_header(rec->err_headers_out, X_REPROXY); } if(reproxy_url==NULL || reproxy_url[0]=='\0') goto PASS_THRU; AP_LOG_VERBOSE(rec, "-- Creating reproxy buckets."); // Drop all content and headers related. while(!APR_BRIGADE_EMPTY(in_bb)) { apr_bucket* b = APR_BRIGADE_FIRST(in_bb); apr_bucket_delete(b); } rec->eos_sent = 0; rec->clength = 0; unset_header(rec, "Content-Length"); //unset_header(rec, "Content-Type"); unset_header(rec, "Content-Encoding"); unset_header(rec, "Last-Modified"); unset_header(rec, "ETag"); // Start reproxy bucket. { apr_off_t content_length = 0; apr_bucket* b = curl_bucket_create(reproxy_url, content_length, in_bb->bucket_alloc, rec); if(b) { APR_BRIGADE_INSERT_TAIL(in_bb, b); while(content_length>0) { AP_LOG_VERBOSE(rec, " curl_next_bucket_create(b, %llu)", content_length); APR_BRIGADE_INSERT_TAIL(in_bb, curl_next_bucket_create(b, content_length)); } APR_BRIGADE_INSERT_TAIL(in_bb, curl_end_bucket_create(b)); APR_BRIGADE_INSERT_TAIL(in_bb, apr_bucket_eos_create(in_bb->bucket_alloc)); } else { AP_LOG_ERR(rec, "curl_bucket_create() failed - %d", rec->status); ap_send_error_response(rec, rec->status); } } AP_LOG_VERBOSE(rec, "-- Create done."); PASS_THRU: AP_LOG_VERBOSE(rec, "-- Filter done."); ap_remove_output_filter(f); return ap_pass_brigade(f->next, in_bb); }