nsapi.c
来自「《jsp编程起步》里面的所有源代码」· C语言 代码 · 共 593 行
C
593 行
#ifdef WIN32#define XP_WIN32#define NSAPI_PUBLIC __declspec(dllexport)#else#define XP_UNIX#define NSAPI_PUBLIC#endif#include <ctype.h>#include <string.h>#include "nsapi.h"#include "../common/cse.h"static config_t g_static_config;static config_t *g_config;static char *g_hostname;static CRITICAL g_lock;voidcse_log(char *fmt, ...){#ifdef DEBUG va_list args; FILE *file = fopen("/tmp/log", "a+"); if (file) { va_start(args, fmt); vfprintf(file, fmt, args); va_end(args); fclose(file); }#endif}voidcse_error(config_t *config, char *format, ...){ char buf[BUF_LENGTH]; va_list args; va_start(args, format); vsprintf(buf, format, args); va_end(args); config->error = cse_strdup(config->p, buf);}void *cse_malloc(int size){ return PERM_MALLOC((size));}void cse_free(config_t *config, void *data) {}voidcse_set_socket_cleanup(int socket, void *pool){}voidcse_kill_socket_cleanup(int socket, void *pool){}void *cse_create_lock(){ return crit_init();}intcse_lock(void *lock){ if (lock) crit_enter((CRITICAL) lock); return 1;}voidcse_unlock(void *lock){ if (lock) crit_exit((CRITICAL) lock);}static voidwrite_env(stream_t *s, Session *sn, Request *rq){ char buf[1024]; char *host; char *query = 0; char *user; char *auth_type; cse_write_string(s, CSE_PROTOCOL, pblock_findval("protocol", rq->reqpb)); cse_write_string(s, CSE_METHOD, pblock_findval("method", rq->reqpb)); cse_write_string(s, CSE_URI, pblock_findval("uri", rq->reqpb)); /* XXX: problems with post */ cse_write_string(s, CSE_QUERY_STRING, pblock_findval("query", rq->reqpb)); if (request_header("host", &host, sn, rq) == REQ_PROCEED && host) { char *p; strcpy(buf, host); p = strchr(buf, ':'); if (p) { *p = 0; cse_write_string(s, CSE_SERVER_NAME, buf); cse_write_string(s, CSE_SERVER_PORT, p + 1); } else { cse_write_string(s, CSE_SERVER_NAME, host); sprintf(buf, "%d", conf_getglobals()->Vport); cse_write_string(s, CSE_SERVER_PORT, buf); } } else { if (! g_hostname) g_hostname = util_hostname(); cse_write_string(s, CSE_SERVER_NAME, g_hostname); sprintf(buf, "%d", conf_getglobals()->Vport); cse_write_string(s, CSE_SERVER_PORT, buf); } /* Can the user configure this so DNS lookups don't occur? if (session_dns(sn)) cse_write_string(s, CSE_REMOTE_HOST, session_dns(sn)); */ cse_write_string(s, CSE_REMOTE_ADDR, pblock_findval("ip", sn->client)); cse_write_string(s, CSE_REMOTE_USER, pblock_findval("auth-user", rq->vars)); cse_write_string(s, CSE_AUTH_TYPE, pblock_findval("auth-type", rq->vars)); sprintf(buf, "%d", s->srun->session); cse_write_string(s, CSE_SESSION_GROUP, buf); /* SSL */ if (security_active) { char *keysize; char *cert; cse_write_string(s, CSE_IS_SECURE, ""); cse_write_string(s, CSE_HEADER, "HTTPS"); cse_write_string(s, CSE_VALUE, "on"); keysize = pblock_findval("keysize", sn->client); if (keysize) { cse_write_string(s, CSE_HEADER, "HTTPS_KEYSIZE"); cse_write_string(s, CSE_VALUE, keysize); } keysize = pblock_findval("secret-keysize", sn->client); if (keysize) { cse_write_string(s, CSE_HEADER, "HTTPS_SECRETKEYSIZE"); cse_write_string(s, CSE_VALUE, keysize); } cert = pblock_findval("auth-cert", rq->vars); if (cert) { cse_write_string(s, CSE_CLIENT_CERT, cert); cse_write_string(s, CSE_HEADER, "SSL_CLIENT_CERT"); cse_write_string(s, CSE_VALUE, cert); } } }/** * Writes headers to srun. */static voidwrite_headers(stream_t *s, Session *sn, Request *rs, int *content_length){ int i; *content_length = -1; if (! rs->headers) return; for (i = 0; i < rs->headers->hsize; i++) { struct pb_entry *entry = rs->headers->ht[i]; for (; entry; entry = entry->next) { char *name = entry->param->name; char *value = entry->param->value; if (! strcasecmp(name, "Content-type")) cse_write_string(s, CSE_CONTENT_TYPE, value); else if (! strcasecmp(name, "Content-length")) { cse_write_string(s, CSE_CONTENT_LENGTH, value); *content_length = atoi(value); } else { cse_write_string(s, CSE_HEADER, name); cse_write_string(s, CSE_VALUE, value); } } }}static intcse_write_response(stream_t *s, int len, Session *sn, Request *rq){ while (len > 0) { int sublen; int writelen; 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 = net_write(sn->csd, s->read_buf + s->read_offset, sublen); /* XXX: Don't close here, just suck up the remaining data. if (writelen < sublen) { cse_log("error2 (%d) %d(%d) %d\n", s->socket, writelen, sublen, errno); return -1; } */ s->read_offset += sublen; len -= sublen; } /* ap_rflush(r); */ return 1;}static intsend_data(stream_t *s, Session *sn, Request *rq, int ack){ int code = CSE_END; char buf[8193]; char key[8193]; char value[8193]; int status; int i; do { int l1, l2, l3; int len; /* ap_reset_timeout(r); */ 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_all(s, buf, len); buf[len] = 0; for (i = 0; buf[i] && buf[i] != ' '; i++) { } if (buf[i]) i++; status = atoi(buf + i); for (; buf[i] && buf[i] != ' '; i++) { } if (buf[i]) i++; protocol_status(sn, rq, status, buf + i); break; case CSE_HEADER: cse_read_all(s, key, len); key[len] = 0; cse_read_string(s, value, sizeof(value)); key[0] = toupper(key[0]); for (i = 1; key[i]; i++) key[i] = tolower(key[i]); pblock_nvinsert(key, value, rq->srvhdrs); break; case CSE_DATA: if (cse_write_response(s, len, sn, rq) < 0) return -1; break; case CSE_SEND_HEADER: protocol_start_response(sn, rq); break; case -1: return -1; default: cse_read_all(s, buf, len); break; } } while (code > 0 && code != CSE_END && code != CSE_CLOSE && code != ack); return code;}static intwrite_request(stream_t *s, Session *sn, Request *rq, config_t *config){ int content_length; int code; char buf[BUF_LENGTH]; int isFirst = 1; netbuf *inbuf = sn->inbuf; write_env(s, sn, rq); write_headers(s, sn, rq, &content_length); /* read post data */ while (content_length > 0) { int len; if (inbuf->pos >= inbuf->cursize) { if (netbuf_grab(inbuf, BUF_LENGTH) <= 0) return 0; } len = inbuf->cursize - inbuf->pos; if (len > BUF_LENGTH) len = BUF_LENGTH; if (len <= 0) return 0; memcpy(buf, inbuf->inbuf + inbuf->pos, len); inbuf->pos += len; content_length -= len; buf[len] = 0; if (! isFirst) { code = send_data(s, sn, rq, CSE_ACK); if (code < 0 || code == CSE_END || code == CSE_CLOSE) break; } cse_write_packet(s, CSE_DATA, buf, len); isFirst = 0; } cse_write_packet(s, CSE_END, 0, 0); code = send_data(s, sn, rq, CSE_END); return code == CSE_END;}static voidnet_printf(Session *sn, char *fmt, ...){ va_list args; char buf[4096]; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); net_write(sn->csd, buf, strlen(buf));}static voidconnection_error(config_t *config, srun_t *srun, Session *sn, Request *rq){ /* //pblock_nvinsert("content-type", "text/html", rq->srvhdrs); //protocol_start_response(sn, rq); */ net_printf(sn, "<html><body bgcolor='white'>\n"); net_printf(sn, "<h1>Cannot contact servlet runner at %s:%d</h1>\n", srun->hostname ? srun->hostname : "localhost", srun->port); net_printf(sn, "</body></html>\n");}static intget_session_index(Request *rq){ int i; int session; char *uri; for (i = 0; i < rq->headers->hsize; i++) { struct pb_entry *entry = rq->headers->ht[i]; for (; entry; entry = entry->next) { char *name = entry->param->name; char *value = entry->param->value; if (strcasecmp(name, "cookie")) continue; session = cse_session_from_string(value, "JSESSIONID="); if (session >= 0) return session; } } uri = pblock_findval("uri", rq->reqpb); return cse_session_from_string(uri, ";JSESSIONID=");}static voidcse_init(char *resin_conf){ g_lock = crit_init(); crit_enter(g_lock); if (! g_config) { g_config = &g_static_config; g_config->path = resin_conf; cse_init_config(g_config); crit_exit(g_lock); }}NSAPI_PUBLIC intcaucho_filter(pblock *pb, Session *sn, Request *rq){ char *host = ""; char *uri = 0; LOG(("start caucho_filter\n")); if (! g_config) { char *conf = pblock_findval("conf", pb); if (conf) cse_init(conf); else cse_init("c:\resin1.1"); } uri = pblock_findval("uri", rq->reqpb); if (cse_match_request(g_config, host, 0, uri)) { param_free(pblock_remove("name", rq->vars)); pblock_nvinsert("name", "resin", rq->vars); return REQ_PROCEED; } return REQ_NOACTION;}NSAPI_PUBLIC intcaucho_service(pblock *pb, Session *sn, Request *rq){ stream_t s; int reuse; int session_index = -1; char *ip = ""; int rand = 0; LOG(("start caucho_service\n")); if (! g_config) { char *conf = pblock_findval("conf", pb); if (conf) cse_init(conf); else cse_init("c:\\resin1.1"); } param_free(pblock_remove("content-type", rq->srvhdrs)); session_index = get_session_index(rq); ip = pblock_findval("ip", sn->client); if (! cse_open_connection(&s, g_config, session_index, ip, rq->req_start, rand, 0)) { connection_error(g_config, g_config->srun_list, sn, rq); return REQ_PROCEED; } reuse = write_request(&s, sn, rq, g_config); /* //ap_kill_timeout(r); //ap_rflush(r); */ if (reuse) cse_recycle(&s); else cse_close(&s, "no reuse"); return REQ_PROCEED;}static voidjvm_status(config_t *config, Session *sn){ int i; stream_t s; net_printf(sn, "<center><table border=2 cellspacing=0 cellpadding=2 width='60%%'>\n"); net_printf(sn, "<tr><th>Host</th>\n"); net_printf(sn, " <th>Connect<br>Timeout</th>\n"); net_printf(sn, " <th>Live<br>Time</th>\n"); net_printf(sn, " <th>Dead<br>Time</th>\n"); net_printf(sn, "</tr>\n"); for (i = 0; i < config->srun_size; i++) { srun_t *srun = config->srun_list + i; int port = srun->port; net_printf(sn, "<tr>"); if (! cse_open(&s, config, srun, 0, 1)) { net_printf(sn, "<td bgcolor='#ff6666'>%s:%d%s (down)</td>", srun->hostname ? srun->hostname : "localhost", port, srun->is_backup ? "*" : ""); } else { net_printf(sn, "<td bgcolor='#66ff66'>%s:%d%s (ok)</td>", srun->hostname ? srun->hostname : "localhost", port, srun->is_backup ? "*" : ""); net_printf(sn, "<td align=right>%d</td><td align=right>%d</td><td align=right>%d</td>", srun->connect_timeout, srun->live_time, srun->dead_time); cse_recycle(&s); continue; } } net_printf(sn, "</table></center>\n");}NSAPI_PUBLIC intcaucho_status(pblock *pb, Session *sn, Request *rq){ location_t *loc; LOG(("start caucho_status\n")); if (! g_config) { char *conf = pblock_findval("conf", pb); if (conf) cse_init(conf); else cse_init("c:\\resin1.1"); } param_free(pblock_remove("content-type", rq->srvhdrs));
pblock_nvinsert("content-type", "text/html", rq->srvhdrs); net_printf(sn, "<html><title>Status : Caucho Servlet Engine</title>\n"); net_printf(sn, "<body bgcolor=white>\n"); net_printf(sn, "<h1>Status : Caucho Servlet Engine</h1>\n"); jvm_status(g_config, sn); net_printf(sn, "<p><center><table border=2 cellspacing=0 cellpadding=2 width='60%%'>\n"); net_printf(sn, "<tr><th width='50%%'>Host\n"); net_printf(sn, " <th>url-pattern\n"); loc = g_config ? g_config->locations : 0; for (; loc; loc = loc->next) { net_printf(sn, "<tr bgcolor='#ffcc66'><td>%s<td>%s%s%s%s</tr>\n", loc->host && loc->host[0] ? loc->host : "*", loc->prefix, ! loc->is_exact && ! loc->suffix ? "/*" : loc->suffix && loc->prefix[0] ? "/" : "", loc->suffix ? "*" : "", loc->suffix ? loc->suffix : ""); } net_printf(sn, "</table></center>\n"); net_printf(sn, "</body></html>\n"); return REQ_PROCEED;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?