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

📄 srun_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/spinlock.h>#include <net/ip.h>#include <asm/uaccess.h>#include "hardcore.h"/** * srun_conn.c handles the connection from resin.o to the JVM process. *//** * Convert an IPV4 address to an integer.  Used as a cheap way of handling * 127.0.0.1 */#define IP(a,b,c,d) ((a << 24) + (b << 16) + (c << 8) + (d))// list of sruns needing closingstatic srun_conn_t *g_srun_close_list;// lock for all srun modificationsstatic spinlock_t g_srun_lock = SPIN_LOCK_UNLOCKED;static void browser_busy(browser_t *browser);/** * Readies an srun for a close.  The actual close will happen later. */static voidsrun_start_close(srun_conn_t *srun){  srun_conn_t *prev = srun->prev;  srun_conn_t *next = srun->next;  if (srun->is_dead)    return;  srun->is_dead = 1;        LOG(("start close %p\n", srun));  if (next)    next->prev = prev;        if (prev)    prev->next = next;  if (srun->parent && srun->parent->conn_head == srun)    srun->parent->conn_head = next;  srun->next = g_srun_close_list;  g_srun_close_list = srun;}/** * Handles the callback when the socket to the srun changes state. * This will happen when the socket connects or when it closes. * * When the connection closes, the kernel will call the data_ready * callback after the state_change callback. * * @param sock the socket between resind and the srun */static voidsrun_state_change(struct sock *sock){  srun_conn_t *srun = sock->user_data;  browser_t *browser;  if (! srun) {    LOG(("resin: srun state_change %x %d null\n", sock, sock->state, srun));    return;  }  browser = srun->browser;    LOG(("resin: srun state_change %x %d %x %s\n",       sock, sock->state, srun, browser_state_name(browser)));  // called when the connection to the srun completes  if (sock->state == TCP_ESTABLISHED) {    // if the state maching is waiting for the connection, move    // to SRUN_START and wake the state machine.    if (browser && browser->state == RHC_SRUN_CONNECTING) {      browser->state = RHC_SRUN_START;      browser_wake(browser);    }  }  // called when the srun connection closes  else {    // if the srun is in the idle list, just remove it    if (! browser) {    }    // if we're trying to connect to the srun, just quit    else if (browser->state == RHC_SRUN_CONNECTING) {      browser->state = RHC_BROWSER_QUIT;      browser->srun_conn = 0;      browser->srun_sock = 0;            browser_wake(browser);    }    // if we're in the middle of a connection, close the connection    else {      browser->state = RHC_BROWSER_QUIT;      browser->srun_conn = 0;      browser->srun_sock = 0;            browser_busy(browser);      browser_wake(browser);    }        sock->user_data = 0;    // If this callback, occurs, the socket has already been closed (??)    // srun->sock = 0;        // Add this srun to the list of sruns to be collected when the    // main thread wakes again.    srun_start_close(srun);  }}/** * Handles the data_ready callback when the srun socket has more data to * read. * * The data_ready callback also occurs when the socket is closed, after * the state_change callback. * * @param sock the socket between resind and the srun * @param bytes in theory, the number of bytes to read.  In reality, this *              seems to be unused. */static voidsrun_data_ready(struct sock *sock, int bytes){  srun_conn_t *srun = sock->user_data;  browser_t *browser = srun ? srun->browser : 0;    LOG(("resin: srun read sock-state:%d browser-state:%s bytes:%d\n",       sock->state, browser_state_name(browser), bytes));  /* If the srun connection has data, mark it and wake the daemon. */  if (browser && sock->state == TCP_ESTABLISHED) {    if (browser->state >= RHC_SRUN_START &&        browser->state <= RHC_SRUN_RECV_DATA) {      browser_wake(browser);    }  }}/** * Connects to a srun. * * @param srun the srun to connect to * @param conn the client connection object * * @return 0 on success */intsrun_connect(srun_t *srun, browser_t *browser){  struct sockaddr_in sin;  struct socket *sock;  struct srun_conn_t *srun_conn;  int error;  LOG(("connect %p r:%p\n", browser->srun_sock, srun));  // XXX: error?? temporary  if (browser->srun_sock)    return -1;  browser->state = RHC_SRUN_CONNECTING;  browser->sin_offset = 0;  browser->sin_length = 0;  // If there's an srun in the recycle list, use it.  if (srun->conn_head) {    struct srun_conn_t *next;        srun_conn = srun->conn_head;    next = srun_conn->next;        if (next)      next->prev = 0;    srun->conn_head = next;        srun_conn->prev = 0;    srun_conn->next = 0;    browser->srun_conn = srun_conn;    srun_conn->browser = browser;    browser->srun_sock = srun_conn->sock;        browser->state = RHC_SRUN_START;    // wake the browser's state machine    browser_wake(browser);        LOG(("reuse srun:%p next:%p\n", srun_conn, srun->conn_head));    return 1;  }  /*   * Otherwise create a new socket connection to the srun.   */  error = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);  if (error < 0) {    LOG(("error %d\n", error));    return error;  }  sin.sin_family = AF_INET;  sin.sin_addr = srun->addr;  sin.sin_port = htons(srun->port);  LOG(("resin: connect(%u.%u.%u.%u:%d)\n",       NIPQUAD(sin.sin_addr.s_addr),       ntohs(sin.sin_port)));    srun_conn = kmalloc(sizeof(srun_conn_t), GFP_KERNEL);  memset(srun_conn, 0, sizeof(srun_conn_t));  srun_conn->parent = srun;  srun_conn->browser = browser;  browser->srun_conn = srun_conn;  browser->srun_sock = sock;  srun_conn->sock = sock;  if (sock->sk) {    sock->sk->user_data = srun_conn;        srun_conn->old_state_change = sock->sk->state_change;    sock->sk->state_change = srun_state_change;        srun_conn->old_data_ready = sock->sk->data_ready;    sock->sk->data_ready = srun_data_ready;  }  else {    // in theory, this should never happen    LOG(("no sk\n"));    return -1;  }  // start connecting to the srun.  error = sock->ops->connect(sock, (struct sockaddr *) &sin, sizeof(sin),                             O_NONBLOCK);  LOG(("resin: connect(%u.%u.%u.%u:%d) -> %d\n",       NIPQUAD(sin.sin_addr.s_addr),       ntohs(sin.sin_port),       error));  if (error >= 0) {    // The connection succeeded immediately (loopback), so move to    // the SRUN_START state and wake the state machine.    browser->state = RHC_SRUN_START;          browser_wake(browser);  }  else if (error == -EAGAIN || error == -EINPROGRESS) {    // The connection would block.  In other words, we'll need to wait    // for the TCP connection to complete and callback at srun_state_change.  }  else {    // The connection failed immediately.  Free the socket and send an    // error message to the browser.    kfree(srun_conn);    browser->state = RHC_BROWSER_QUIT;    browser->srun_conn = 0;    browser->srun_sock = 0;    sock_release(sock);    browser_busy(browser);    browser_wake(browser);  }  return 1;}/** * Sends the connection failed error message to the browser.

⌨️ 快捷键说明

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