📄 mod_caucho.c
字号:
write_headers(stream_t *s, request_rec *r){ const apr_array_header_t *header = apr_table_elts(r->headers_in); apr_table_entry_t *headers = (apr_table_entry_t *) header->elts; int i; for (i = 0; i < header->nelts; ++i) { if (! headers[i].key) continue; /* * Content-type and Content-Length are special cased for a little * added efficiency. */ if (! strcasecmp(headers[i].key, "Content-type")) cse_write_string(s, CSE_CONTENT_TYPE, headers[i].val); else if (! strcasecmp(headers[i].key, "Content-length")) cse_write_string(s, CSE_CONTENT_LENGTH, headers[i].val); else { cse_write_string(s, CSE_HEADER, headers[i].key); cse_write_string(s, CSE_VALUE, headers[i].val); } }}static voidwrite_added_headers(stream_t *s, request_rec *r){ const apr_array_header_t *header = apr_table_elts(r->subprocess_env); apr_table_entry_t *headers = (apr_table_entry_t *) header->elts; int i; for (i = 0; i < header->nelts; ++i) { if (! headers[i].key) continue; if (! strcmp(headers[i].key, "HTTPS") && ! strcmp(headers[i].val, "on")) { cse_write_string(s, CSE_IS_SECURE, ""); } else if (! r->user && ! strcmp(headers[i].key, "SSL_CLIENT_DN")) cse_write_string(s, CSE_REMOTE_USER, headers[i].val); cse_write_string(s, CSE_HEADER, headers[i].key); cse_write_string(s, CSE_VALUE, headers[i].val); }}/** * Writes a response from srun to the client */static intcse_write_response(stream_t *s, int len, request_rec *r){ while (len > 0) { int sublen; int writelen; int sentlen; if (s->read_offset >= s->read_length && cse_fill_buffer(s) < 0) return -1; sublen = s->read_length - s->read_offset; if (len < sublen) sublen = len; writelen = sublen; while (writelen > 0) { sentlen = ap_rwrite(s->read_buf + s->read_offset, writelen, r); if (sentlen < 0) { cse_close(s, "write"); return -1; } writelen -= sublen; } s->read_offset += sublen; len -= sublen; } return 1;}/** * Copy data from the JVM to the browser. */static intsend_data(stream_t *s, request_rec *r, int ack, int *keepalive){ int code = CSE_END; char buf[8193]; char key[8193]; char value[8193]; int i; if (cse_fill_buffer(s) < 0) return -1; do { int l1, l2, l3; int len; code = cse_read_byte(s); l1 = cse_read_byte(s) & 0xff; l2 = cse_read_byte(s) & 0xff; l3 = cse_read_byte(s); len = (l1 << 16) + (l2 << 8) + (l3 & 0xff); if (s->socket < 0) return -1; switch (code) { case CSE_STATUS: cse_read_limit(s, buf, sizeof(buf), len); for (i = 0; buf[i] && buf[i] != ' '; i++) { } i++; r->status = atoi(buf + i); r->status_line = apr_pstrdup(r->pool, buf + i); break; case CSE_HEADER: cse_read_limit(s, key, sizeof(key), len); cse_read_string(s, value, sizeof(value)); if (! strcasecmp(key, "content-type")) r->content_type = apr_pstrdup(r->pool, value); else apr_table_add(r->headers_out, key, value); break; case CSE_DATA: if (cse_write_response(s, len, r) < 0) return -1; break; case CSE_FLUSH: ap_rflush(r); break; case CSE_KEEPALIVE: *keepalive = 1; break; case CSE_SEND_HEADER: break; case -1: break; default: cse_skip(s, len); break; } } while (code > 0 && code != CSE_END && code != CSE_CLOSE && code != ack); return code;}/** * handles a client request */static intwrite_request(stream_t *s, request_rec *r, config_t *config, int *keepalive, int session_index, int backup_index){ int len; int code; int write_length; write_env(s, r); write_headers(s, r); write_added_headers(s, r); /* read post data */ if (ap_should_client_block(r)) { char buf[BUF_LENGTH]; int isFirst = 1; while ((len = ap_get_client_block(r, buf, BUF_LENGTH)) > 0) { cse_write_packet(s, CSE_DATA, buf, len); if (! isFirst) { code = send_data(s, r, CSE_ACK, keepalive); if (code < 0 || code == CSE_END || code == CSE_CLOSE) break; } isFirst = 0; } } cse_write_packet(s, CSE_END, 0, 0); code = send_data(s, r, CSE_END, keepalive); write_length = s->write_length; if (code == CSE_END) return OK; else if (code >= 0 || s->sent_data) return 0; return HTTP_SERVICE_UNAVAILABLE;}/** * Handle a request. */static intcaucho_request(request_rec *r){ config_t *config = cse_get_module_config(r); stream_t s; int retval; int keepalive = 0; int reuse; int session_index; int backup_index = 0; char *ip; srun_t *srun; unsigned int request_time = (unsigned int) (r->request_time / 1000000); if ((retval = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK))) return retval; session_index = get_session_index(config, r, &backup_index); ip = r->connection->remote_ip; if (! cse_open_connection(&s, config, session_index, backup_index, request_time, r->pool)) { return HTTP_SERVICE_UNAVAILABLE; } srun = s.srun->srun; cse_lock(srun->lock); srun->active_sockets++; cse_unlock(srun->lock); reuse = write_request(&s, r, config, &keepalive, session_index, backup_index); cse_lock(srun->lock); srun->active_sockets--; cse_unlock(srun->lock); if (reuse == OK) cse_recycle(&s, request_time); else cse_close(&s, "no reuse"); if (reuse == HTTP_SERVICE_UNAVAILABLE) return reuse; else return OK;}/** * Print the statistics for each JVM. */static voidjvm_status(config_t *config, request_rec *r){ int i; stream_t s; ap_rputs("<center><table border=2 width='80%'>\n", r); ap_rputs("<tr><th>Host</th>\n", r); ap_rputs(" <th>Active</th>\n", r); ap_rputs(" <th>Pooled</th>\n", r); ap_rputs(" <th>Connect<br>Timeout</th>\n", r); ap_rputs(" <th>Live<br>Time</th>\n", r); ap_rputs(" <th>Dead<br>Time</th>\n", r); ap_rputs("</tr>\n", r); for (i = 0; i < config->srun_size; i++) { srun_item_t *srun_item = config->srun_list + i; srun_t *srun = srun_item->srun; int port; int pool_count; if (! srun) continue; port = srun->port; pool_count = ((srun->conn_head - srun->conn_tail + CONN_POOL_SIZE) % CONN_POOL_SIZE); ap_rputs("<tr>", r); if (! cse_open(&s, config, srun_item, r->pool, 0)) { ap_rprintf(r, "<td bgcolor='#ff6666'>%d. %s:%d%s (down)</td>", srun_item->session + 1, srun->hostname ? srun->hostname : "localhost", port, srun_item->is_backup ? "*" : ""); } else { ap_rprintf(r, "<td bgcolor='#66ff66'>%d. %s:%d%s (ok)</td>", srun_item->session + 1, srun->hostname ? srun->hostname : "localhost", port, srun_item->is_backup ? "*" : ""); } /* This needs to be close, because cse_open doesn't use recycle. */ cse_close(&s, "caucho-status"); LOG(("close\n")); ap_rprintf(r, "<td align=right>%d</td><td align=right>%d</td>", srun->active_sockets, pool_count); ap_rprintf(r, "<td align=right>%d</td><td align=right>%d</td><td align=right>%d</td>", srun->connect_timeout, srun->live_time, srun->dead_time); ap_rputs("</tr>\n", r); } ap_rputs("</table></center>\n", r);}/** * Print a summary of the configuration so users can understand what's * going on. Ping the server to check that it's up. */static intcaucho_status(request_rec *r){ config_t *config; web_app_t *app; location_t *loc; if (! r->handler || strcmp(r->handler, "caucho-status")) return DECLINED; config = cse_get_module_config(r); r->content_type = "text/html"; if (r->header_only) return OK; ap_rputs("<html><title>Status : Caucho Servlet Engine</title>\n", r); ap_rputs("<body bgcolor=white>\n", r); ap_rputs("<h1>Status : Caucho Servlet Engine</h1>\n", r); if (! config) return OK; if (config->error) ap_rprintf(r, "<h2 color='red'>Error : %s</h2>\n", config->error); jvm_status(config, r); ap_rputs("<p><center><table border=2 cellspacing=0 cellpadding=2 width='80%'>\n", r); ap_rputs("<tr><th>Host\n", r); ap_rputs(" <th>url-pattern\n", r); app = config ? config->applications : 0; for (; app; app = app->next) { for (loc = app->locations; loc; loc = loc->next) { char port[16]; if (app->host_alias_length > 0 && app->host_aliases[0]->port > 0) sprintf(port, ":%d", app->host_aliases[0]->port); else port[0] = 0; ap_rprintf(r, "<tr bgcolor='#ffcc66'><td>%s%s%s<td>%s%s%s%s%s</tr>\n", app->host && app->host[0] ? app->host : "", port, *app->prefix ? app->prefix : "/", loc->prefix, ! loc->is_exact && ! loc->suffix ? "/*" : loc->suffix && loc->prefix[0] ? "/" : "", loc->suffix ? "*" : "", loc->suffix ? loc->suffix : "", loc->ignore ? " (ignore)" : ""); } } ap_rputs("</table></center>\n", r); ap_rputs("<hr>", r); ap_rprintf(r, "<em>%s<em>", VERSION); ap_rputs("</body></html>\n", r); return OK;}/** * Look at the request to see if Caucho should handle it. */static intcse_dispatch(request_rec *r){ config_t *config = cse_get_module_config(r); const char *host = ap_get_server_name(r); const char *uri = r->uri; char *url_rewrite; unsigned int request_time = (unsigned int) (r->request_time / 1000000); int len; if (config == NULL || ! uri) return DECLINED; LOG(("[%d] host %s\n", getpid(), host ? host : "null")); cse_update_config(config, request_time); len = strlen(uri); if (! config->disable_caucho_status && len >= sizeof("/caucho-status") - 1 && ! strcmp(uri + len - sizeof("/caucho-status") + 1, "/caucho-status")) { r->handler = "caucho-status"; return caucho_status(r); } /* Check for exact virtual host match */ if (cse_match_request(config, host, ap_get_server_port(r), uri, 0) || ! strcmp(r->handler, "caucho-request")) { LOG(("[%d] match %s:%s\n", getpid(), host ? host : "null", uri)); return caucho_request(r); } if (config->session_url_prefix) { char *new_uri; new_uri = strstr(uri, config->session_url_prefix); if (new_uri) *new_uri = 0; } /* Strip session encoding from static files. */ if (r->filename && config->session_url_prefix) { url_rewrite = strstr(r->filename, config->session_url_prefix); if (url_rewrite) { *url_rewrite = 0; /* if (stat(r->filename, &r->finfo) < 0) r->finfo.st_mode = 0; */ } } return DECLINED;}/* * Only needed configuration is pointer to resin.conf */static command_rec caucho_commands[] = { {"CauchoConfigFile", cse_config_file_command, NULL, RSRC_CONF|ACCESS_CONF, TAKE1, "Pointer to the Caucho configuration file."}, {"CauchoServerRoot", cse_server_root_command, NULL, RSRC_CONF|ACCESS_CONF, TAKE1, "Pointer to the Caucho server root."}, {"CauchoHost", cse_host_command, NULL, RSRC_CONF|ACCESS_CONF, TAKE12, "Adds a Caucho host."}, {"CauchoBackup", cse_backup_command, NULL, RSRC_CONF|ACCESS_CONF, TAKE12, "Adds a Caucho backup host."}, {NULL}};static void caucho_register_hooks(apr_pool_t *p){ ap_hook_handler(cse_dispatch, NULL, NULL, APR_HOOK_FIRST);}/* Dispatch list for API hooks */module AP_MODULE_DECLARE_DATA caucho_module = { STANDARD20_MODULE_STUFF, cse_create_dir_config, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ caucho_commands, /* table of config file commands */ caucho_register_hooks /* register hooks */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -