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 + -
显示快捷键?