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

📄 browser_conn.c

📁 resinweb服务器源文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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/sched.h>#include <linux/interrupt.h>#include <linux/in.h>#include <linux/inet.h>#include <linux/time.h>#include <net/ip.h>#include <asm/uaccess.h>#include "hardcore.h"static browser_t *g_browser_ready;static spinlock_t g_ready_lock = SPIN_LOCK_UNLOCKED;static browser_t *g_browser_free;static browser_t *g_browser_list;static int g_has_accept = 0;/** * Wakes the browser connection, readying it for execution by browser_execute. */voidbrowser_wake(browser_t *browser){  if (browser->is_active)    return;  spin_lock_irq(&g_ready_lock);  if (! browser->is_active) {    browser->is_active = 1;    browser->next = g_browser_ready;    g_browser_ready = browser;  }    spin_unlock_irq(&g_ready_lock);  resind_wake();}/** * The server socket receives callbacks when accepting a new client socket. * Each client is associated with a connection_t structure. */static voidaccept_state_change(struct sock *sock){  LOG(("resin: accept state_change %p %d %p\n",       sock, sock->state, sock->socket));  if (sock->state == TCP_ESTABLISHED) {    g_has_accept = 1;        // Wake the server to actually accept the request    resind_wake();  }}/** * Handles the callback when the socket to the browser changes state. * Normally, this only occurs on socket close. * * @param sock the socket between resind and the client */static voidbrowser_state_change(struct sock *sock){  browser_t *browser = sock->user_data;    LOG(("resin: browser state_change %x %d\n", sock, sock->state));  if (sock->state == TCP_CLOSE && browser) {    sock->user_data = 0;    browser->state = RHC_BROWSER_QUIT;    browser->is_dead = 1;    browser_wake(browser);  }}/** * Handles the callback when the socket to the browser has more data to * read. * * @param sock the socket between resind and the browser * @param bytes in theory, the number of bytes to read.  In reality, this *              seems to be unused. */static voidbrowser_data_ready(struct sock *sock, int bytes){  browser_t *browser = sock->user_data;    LOG(("resin: browser read %x %d %p %d\n", sock, sock->state, browser, bytes));  if (sock->state == TCP_ESTABLISHED && browser)    browser_wake(browser);}/** * Handles the callback when the socket to the browser has space for * a write * * @param sock the socket between resind and the browser */static voidbrowser_write_space(struct sock *sock){  browser_t *browser = sock->user_data;    if (browser && browser->state == RHC_BROWSER_WRITE) {    LOG(("resin: browser write %x %d %p %d\n",         sock, sock->state, browser, browser->state));      browser_wake(browser);  }}/** * create a new browser browserection */static voidbrowser_create(){  browser_t *browser = kmalloc(sizeof(browser_t), GFP_KERNEL);  if (browser) {    memset(browser, 0, sizeof(browser_t));        browser->resin = &g_resin;        browser->next = g_browser_free;    g_browser_free = browser;        browser->next_browser = g_browser_list;    if (g_browser_list)      g_browser_list->prev_browser = browser;    g_browser_list = browser;  }  else    LOG(("can't allocate\n"));}/** * Allocate a new browser object */static browser_t *browser_allocate(resin_t *resin){  browser_t *browser = g_browser_free;    if (browser) {    g_browser_free = g_browser_free->next;    browser->next = 0;    browser->is_active = 0;    browser->is_dead = 0;    browser->cache = 0;  }  return browser;}/** * Accept a socket from the server socket. */static intbrowser_accept(resin_t *resin){  struct sock *ss = resin->accept_socket->sk;  struct sock *sock;  browser_t *browser;  struct timeval time_now;  int err;  if (! ss)    return 0;    sock = ss->prot->accept(ss, O_NONBLOCK, &err);  if (! sock)    return 0;  LOG(("accept %p\n", sock));  browser = browser_allocate(resin);  // can't allocate the browser, so kill it  // XXX: how does the listen queue work?  if (! browser) {    sock->prot->close(sock, 0);    return 1;  }  // Technically the wrong socket structure, but sendmsg needs the socket  // Hopefully, this won't confuse anything.  sock->socket = browser->resin->accept_socket;  browser->browser_sock = sock;  browser->is_dead = 0;  browser->cin_offset = 0;  browser->cin_length = 0;  browser->post_offset = 0;  browser->in_header = 0;  browser->keepalive = 0;  browser->request_length = -1;  browser->srun_conn = 0;  browser->srun_sock = 0;      do_gettimeofday(&time_now);  browser->now = time_now.tv_sec;  browser->cache = 0;  browser->expires = 0;  browser->cout_offset = 0;  browser->cout_length = 0;  browser->iov_index = 0;    sock->user_data = browser;  browser->old_state_change = sock->state_change;  sock->state_change = browser_state_change;    browser->old_data_ready = sock->data_ready;  sock->data_ready = browser_data_ready;    browser->old_write_space = sock->write_space;  sock->write_space = browser_write_space;  // Wake the browser in case it has some data  browser->state = RHC_BROWSER_START;  browser_wake(browser);  return 1;}/** * Closes a browser */voidbrowser_close(browser_t *browser){  LOG(("close %p\n", browser));    if (browser->browser_sock) {    struct sock *sock = browser->browser_sock;    browser->browser_sock = 0;    sock->socket = 0;    sock->user_data = 0;    sock->state_change = browser->old_state_change;    sock->data_ready = browser->old_data_ready;    sock->write_space = browser->old_write_space;        sock->prot->close(sock, 0);  }  // make the srun available to subsequent requests  if (browser->srun_conn)    srun_recycle(browser->srun_conn);      browser->srun_conn = 0;  browser->srun_sock = 0;  if (browser->cache)    cache_kill(browser);  browser->next = g_browser_free;  g_browser_free = browser;}/** * Reads from a socket * * @param sock the socket receiving the browser * @param buf the buffer receiving the data * @param len the length of the expected data * * @return the number of bytes actually received */intsocket_recv(struct sock *sock, char *buf, int len){  mm_segment_t oldfs;  struct msghdr msg;  struct iovec iov;  int addr_len = 0;  if (! sock || len <= 0)    return -1;  msg.msg_name =  0;  msg.msg_namelen = 0;  msg.msg_iov = &iov;  msg.msg_iovlen = 1;  msg.msg_control = 0;  msg.msg_controllen = 0;  iov.iov_base = buf;  iov.iov_len = len;        LOG(("socket read %d\n", len));  oldfs = get_fs(); set_fs(KERNEL_DS);  len = sock->prot->recvmsg(sock, &msg, len, 1, 0, &addr_len);  set_fs(oldfs);  LOG(("post read %d\n", len));  return len;}/** * Reads from the client socket into the client in buffer (cin_*) * * If there isn't enough room in the buffer, e.g. for pipelined requests, * shift the buffer down. * * @param browser the browser */static intbrowser_recv(browser_t *browser){  char *buf = browser->cin_buf;  int head = browser->cin_offset;  int tail = browser->cin_length;  int capacity = sizeof(browser->cin_buf);  int len;  LOG(("stuff in %d head %d tail %d cap %d\n", browser->in_header,       head, tail, capacity));    if (browser->in_header) {  }  else if (head == tail) {    browser->cin_offset = 0;    tail = 0;  }  else if (2 * head < capacity || capacity < 2 * tail) {    int i;    int delta = tail - head;    for (i = 0; i < delta; i++)      buf[i] = buf[i + head];    browser->cin_offset = 0;    tail = delta;  }  LOG(("pre-recv tail:%d\n", tail));  len = socket_recv(browser->browser_sock, buf + tail, capacity - tail);  LOG(("post-recv tail:%d %d\n", tail, len));    if (len > 0)    browser->cin_length = tail + len;  else if (len == -EAGAIN || len == -EWOULDBLOCK)    browser->cin_length = tail;  else {    browser->cin_length = tail;    browser->state = RHC_BROWSER_QUIT;    browser_wake(browser);  }  return len;

⌨️ 快捷键说明

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