⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 srun_protocol.c

📁 resinweb服务器源文件
💻 C
字号:
/* * Copyright (c) 1998-2001 Caucho Technology -- all rights reserved * * Caucho Technology permits redistribution, modification and use * of this file in source and binary form ("the Software") under the * Caucho Developer Source License ("the License").  The following * conditions must be met: * * 1. Each copy or derived work of the Software must preserve the copyright *    notice and this notice unmodified. * * 2. Redistributions of the Software in source or binary form must include  *    an unmodified copy of the License, normally in a plain ASCII text * * 3. The names "Resin" or "Caucho" are trademarks of Caucho Technology and *    may not be used to endorse products derived from this software. *    "Resin" or "Caucho" may not appear in the names of products derived *    from this software. * * 4. Caucho Technology requests that attribution be given to Resin *    in any manner possible.  We suggest using the "Resin Powered" *    button or creating a "powered by Resin(tm)" link to *    http://www.caucho.com for each page served by Resin. * * This Software is provided "AS IS," without a warranty of any kind.  * ALL EXPRESS OR IMPLIED REPRESENTATIONS AND WARRANTIES, INCLUDING ANY * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. * * CAUCHO TECHNOLOGY AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES * SUFFERED BY LICENSEE OR ANY THIRD PARTY AS A RESULT OF USING OR * DISTRIBUTING SOFTWARE. IN NO EVENT WILL CAUCHO OR ITS LICENSORS BE LIABLE * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR * INABILITY TO USE SOFTWARE, EVEN IF HE HAS BEEN ADVISED OF THE POSSIBILITY * OF SUCH DAMAGES.       * * @author Scott Ferguson */#include <linux/kernel.h>#include <linux/socket.h>#include <linux/proc_fs.h>#include <linux/in.h>#include "hardcore.h"#include "../common/srun.h"/** * Writes a string to the buffer. */static intwrite_string(char *buf, int offset, int code, char *string){  int i = offset;  int len = 0;  int ch;  if (! string)    return offset;  // XXX: check total length  buf[i] = code;  i += 4;  for (len = 0; (ch = string[len]); len++)    buf[i++] = ch;  buf[offset + 1] = len >> 16;  buf[offset + 2] = len >> 8;  buf[offset + 3] = len;  return i;}/** * Writes a code packed to the buffer. */static intwrite_packet(char *buf, int offset, int code, char *data, int len){  // XXX: check total length  buf[offset] = code;  buf[offset + 1] = len >> 16;  buf[offset + 2] = len >> 8;  buf[offset + 3] = len;  memcpy(buf + offset + 4, data, len);  return offset + 4 + len;}/** * Writes a code packed to the buffer. */static intwrite_code(char *buf, int offset, int code){  // XXX: check total length  buf[offset] = code;  buf[offset + 1] = 0;  buf[offset + 2] = 0;  buf[offset + 3] = 0;  return offset + 4;}/** * Sends a POST continuation to the servlet runner. * * Called from either RHC_SRUN_START or RHC_SRUN_POST */voidsrun_send_post(browser_t *browser){  int len = browser->request_length;    int sublen = browser->cin_length - browser->cin_offset;  char *data = browser->cin_buf + browser->cin_offset;  int offset = 0;  browser->next_state = browser->state;  if (len > 0) {    LOG(("sp post cl:%d cin:%d\n", len, sublen));    if (sublen == 0) {      browser->state = RHC_SRUN_POST;      browser_wake(browser);      return;    }        if (sublen > len)      sublen = len;    if (sublen > 4096 - 8)      sublen = 4096 - 8;          offset = write_packet(browser->sout_buf, offset, CSE_DATA, data, sublen);    len -= sublen;    browser->request_length = len;    browser->cin_offset += sublen;  }    if (len <= 0) {    LOG(("sp end\n"));    offset = write_code(browser->sout_buf, offset, CSE_END);  }    browser->sout_offset = 0;  browser->sout_length = offset;  browser->state = RHC_SRUN_SEND;  browser_wake(browser);  return;}/** * Sends the request to the servlet runner. * * Called from either RHC_SRUN_START or RHC_SRUN_POST */intresin_srun(browser_t *browser){  char *buf = browser->sout_buf;  int offset = 0;  int i;  browser->in_header = 0;  LOG(("srun %s\n", browser->url));  offset = write_string(buf, offset, CSE_METHOD, browser->method);  offset = write_string(buf, offset, CSE_URI, browser->url);  offset = write_string(buf, offset, CSE_PROTOCOL, browser->protocol);  for (i = 0; i < browser->header_count; i++) {    offset = write_string(buf, offset, CSE_HEADER, browser->key[i]);    offset = write_string(buf, offset, CSE_VALUE, browser->value[i]);  }  if (*browser->method == 'P' && browser->request_length >= 0) {    int len = browser->request_length;    browser->post_offset = browser->cin_length;    LOG(("post %s cl:%d cin:%d\n", browser->method, len,         browser->cin_length - browser->cin_offset));        if (len <= browser->cin_length - browser->cin_offset) {      char *data = browser->cin_buf + browser->cin_offset;            offset = write_packet(buf, offset, CSE_DATA, data, len);      browser->request_length -= len;      browser->cin_offset += len;    }    else {      char *data = browser->cin_buf + browser->cin_offset;      int sublen = browser->cin_length - browser->cin_offset;      offset = write_packet(buf, offset, CSE_DATA, data, sublen);      browser->request_length -= sublen;      browser->cin_offset += sublen;    }  }  if (browser->request_length > 0) {    browser->next_state = RHC_SRUN_RECV_HEADER;    browser->state = RHC_SRUN_SEND;  } else {    offset = write_code(buf, offset, CSE_END);    browser->next_state = RHC_SRUN_RECV_HEADER;    browser->state = RHC_SRUN_SEND;  }    browser->sout_offset = 0;  browser->sout_length = offset;  return 0;}/** * Writes a string to the buffer. */static intcse_write(char *buf, int off, char *str){  while (*str)    buf[off++] = *str++;  return off;}/** * Proxies the headers from the srun to the browser. * * @return 1 if the browser should be rewoken */intsrun_read_header(browser_t *browser){  char *buf = browser->sin_buf;  int off = browser->sin_offset;  int len = browser->sin_length;  int code;  int packet_len = browser->packet_len;  int state = browser->state;  int next_state = browser->next_state;  int i;  char *out_buf = browser->cout_buf;  int out_len = browser->cout_length;  int is_done = 0;  struct iovec *iov = browser->iov;  int iov_index = 0;  while (! is_done && off < len) {    switch (state) {    case RHC_SRUN_RECV_HEADER:    case RHC_SRUN_BODY:      // If don't have the 4 byte header, wait for more data      if (len - off < 4) {        if (off > 0) {          for (i = len - off - 1; i >= 0; i--)            buf[i] = buf[off + i];          browser->sin_offset = 0;          browser->sin_length = len - off;        }        else {          browser->sin_offset = off;          browser->sin_length = len;        }        browser->state = state;        return 1;      }            code = buf[off];      packet_len = (((buf[off + 1] & 0xff) << 16) +                     ((buf[off + 2] & 0xff) << 8) +                     ((buf[off + 3] & 0xff)));            switch (code) {      case CSE_STATUS:        LOG(("status %d\n", packet_len));        state = RHC_SRUN_RECV_STATUS;        off += 4;        break;              case CSE_HEADER:        // LOG(("header %d\n", packet_len));        state = RHC_SRUN_RECV_KEY;        off += 4;        break;      case CSE_VALUE:        // LOG(("value %d\n", packet_len));        state = RHC_SRUN_RECV_VALUE;        off += 4;        break;      case CSE_SEND_HEADER:        if (browser->is_chunked)          out_len = cse_write(out_buf, out_len,                              "Transfer-Encoding: chunked\r\n");                    out_len = cse_write(out_buf, out_len, "Date: ");        out_len += format_now(out_buf + out_len);                out_buf[out_len++] = '\r';        out_buf[out_len++] = '\n';                out_buf[out_len++] = '\r';        out_buf[out_len++] = '\n';                LOG(("header %s %s\n",             browser_state_name(browser),             out_buf));        // XXX: more caching        if (browser->status == 200 && browser->now < browser->expires) {          cache_start(browser);        }        LOG(("headersdone %s time-delta:%d\n",             browser_state_name(browser),             browser->now - browser->expires));        state = RHC_SRUN_BODY;        off += 4;        iov[0].iov_base = out_buf;        iov[0].iov_len = out_len;        iov_index = 1;        break;              case CSE_DATA:        LOG(("data %d\n", packet_len));        off += 4;        state = RHC_SRUN_RECV_DATA;        if (browser->is_chunked && packet_len > 0) {                  }        break;              case CSE_ACK:        LOG(("ack %d\n", packet_len));        off += 4;        browser->state = state;        browser->next_state = next_state;        srun_send_post(browser);        state = browser->state;        next_state = browser->next_state;        is_done = 1;        break;              case CSE_END:      case CSE_CLOSE:        LOG(("quit %d\n", packet_len));        state = RHC_BROWSER_QUIT;        off += 4;        is_done = 1;        if (browser->cache)          cache_finish(browser);        break;      default:        LOG(("skip %c %d\n", code, packet_len));        off += 4;         if (packet_len > 0) {          next_state = state;          state = RHC_SRUN_RECV_SKIP;        }        break;      }      break;    case RHC_SRUN_RECV_STATUS:      out_len = 0;      browser->cout_length = 0;      browser->cout_offset = 0;      // XXX: must restrict length      for (; packet_len > 0 && off < len; packet_len--, off++)        out_buf[out_len++] = buf[off];      if (packet_len <= 0) {        // HTTP/1.x nnn msg        browser->status = (100 * (out_buf[9] - '0') +                           10 * (out_buf[10] - '0') +                           out_buf[11] - '0');        out_buf[out_len++] = '\r';        out_buf[out_len++] = '\n';        out_buf[out_len] = 0;        if (browser->version == HTTP_1_1) {          browser->is_chunked = out_buf[7] == '1';          if (! browser->keepalive)            out_len = cse_write(out_buf, out_len, "Connection: close\r\n");        }        else          browser->is_chunked = 0;                out_len = cse_write(out_buf, out_len, "Server: ResinHardCore/1.3\r\n");        out_buf[out_len] = 0;                state = RHC_SRUN_RECV_HEADER;                browser->key_start = out_buf + out_len;      }      break;    case RHC_SRUN_RECV_KEY:      // XXX: must restrict length      for (; packet_len > 0 && off < len; packet_len--, off++)        out_buf[out_len++] = buf[off];      if (packet_len <= 0) {        out_buf[out_len++] = ':';        out_buf[out_len++] = ' ';        out_buf[out_len] = 0;                // LOG(("key %s\n", browser->key_start));        browser->value_start = out_buf + out_len;                state = RHC_SRUN_RECV_HEADER;      }      break;    case RHC_SRUN_RECV_VALUE:      // XXX: must restrict length      for (; packet_len > 0 && off < len; packet_len--, off++)        out_buf[out_len++] = buf[off];      if (packet_len <= 0) {        char *key = browser->key_start;                out_buf[out_len++] = '\r';        out_buf[out_len++] = '\n';        out_buf[out_len] = 0;                LOG(("%s", browser->key_start));        switch (*key) {        case 'e': case 'E':          if (strnicmp(key, "Expires:", 8)) {            browser->expires = parse_date(browser->value_start);            LOG(("Expires %d\n", browser->expires));          }          break;        case 'c': case 'C':          if (! strnicmp(key, "Content-Length:", sizeof("Context-Length:")))            browser->is_chunked = 0;          break;        }                state = RHC_SRUN_RECV_HEADER;        browser->key_start = out_buf + out_len;      }      break;    case RHC_SRUN_RECV_DATA:      LOG(("recv-data %d %d\n", packet_len, len - off));      if (packet_len <= len - off) {        iov[iov_index].iov_base = buf + off;        iov[iov_index].iov_len = packet_len;        off += packet_len;        state = RHC_SRUN_BODY;      }      else {        iov[iov_index].iov_base = buf + off;        iov[iov_index].iov_len = len - off;        packet_len -= len - off;        off = len;      }            if (browser->cache)        cache_write(browser, iov[iov_index].iov_base, iov[iov_index].iov_len);            iov_index++;      break;    case RHC_SRUN_RECV_SKIP:      if (packet_len < len - off) {        off += packet_len;        state = next_state;      }      else {        packet_len -= len - off;        off = len;      }      break;    default:      is_done = 1;      break;    }  }  LOG(("done %d %d\n", off, len));  if (off < len) {    browser->sin_offset = off;    browser->sin_length = len;  }  else {    browser->sin_offset = 0;    browser->sin_length = 0;  }  browser->cout_length = out_len;  browser->packet_len = packet_len;  browser->state = state;  browser->next_state = next_state;  if (iov_index > 0) {    browser->write_state = state;    browser->state = RHC_BROWSER_WRITE;    browser->iov_index = iov_index;        return browser_write_iov(browser) > 0;  }  else    return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -