Chinaunix首页 | 论坛 | 博客
  • 博客访问: 63673
  • 博文数量: 21
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 236
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-05 21:34
文章分类

全部博文(21)

文章存档

2015年(21)

我的朋友

分类: LINUX

2015-08-07 23:52:29


点击(此处)折叠或打开

  1. //start from the very beginning,and to create greatness
  2. //@author: Chuangwei Lin
  3. //@E-mail:979951191@qq.com
  4. //@brief:客户端请求分析
  5. #include "lcw_shttpd.h"
  6. extern void Error_400(struct worker_ctl* wctl);
  7. extern void Error_403(struct worker_ctl* wctl);
  8. extern void Error_404(struct worker_ctl* wctl);
  9. extern void Error_505(struct worker_ctl* wctl);

  10. static struct http_header http_headers[] =
  11. {
  12.     {16,    HDR_INT,    OFFSET(cl),            "Content-Length: "        },
  13.     {14,    HDR_STRING,    OFFSET(ct),            "Content-Type: "        },
  14.     {12,    HDR_STRING,    OFFSET(useragent),    "User-Agent: "            },
  15.     {19,    HDR_DATE,    OFFSET(ims),        "If-Modified-Since: "    },
  16.     {15,    HDR_STRING,    OFFSET(auth),        "Authorization: "        },
  17.     {9,        HDR_STRING,    OFFSET(referer),    "Referer: "                },
  18.     {8,        HDR_STRING,    OFFSET(cookie),        "Cookie: "                },
  19.     {10,    HDR_STRING,    OFFSET(location),    "Location: "            },
  20.     {8,        HDR_INT,    OFFSET(status),        "Status: "                },
  21.     {7,        HDR_STRING,    OFFSET(range),        "Range: "                },
  22.     {12,    HDR_STRING,    OFFSET(connection),    "Connection: "            },
  23.     {19,    HDR_STRING,    OFFSET(transenc),    "Transfer-Encoding: "    },
  24.     {0,        HDR_INT,    0,                    NULL                    }
  25. };
  26. extern struct vec _shttpd_methods[];
  27. struct conf_opts conf_para;
  28. /******************************************************
  29. 函数名:montoi(char *s)
  30. 参数:
  31. 功能:将月份转化为数字
  32. *******************************************************/
  33. static int montoi(char *s)
  34. {
  35.     DBGPRINT("LCW==>montoi\n");
  36.     int retval = -1;
  37.     static char *ar[] =
  38.      { //月份数组
  39.         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  40.         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  41.     };
  42.     size_t i;
  43.     for (i = 0; i < sizeof(ar) / sizeof(ar[0]); i++)
  44.     {
  45.         if (!strcmp(s, ar[i]))
  46.         {//遍历查找
  47.             retval = i;
  48.             goto EXITmontoi;
  49.         }
  50.     }    
  51.     DBGPRINT("LCW<==montoi\n");
  52. EXITmontoi:
  53.     return retval;
  54. }
  55. /******************************************************
  56. 函数名:date_to_epoch(char *s)
  57. 参数:
  58. 功能:Parse date-time string, and return the corresponding time_t value
  59. *******************************************************/
  60. static time_t date_to_epoch(char *s)
  61. {
  62.     DBGPRINT("LCW==>date_to_epoch\n");
  63.     struct tm    tm;
  64.     char mon[32];
  65.     int    sec, min, hour, mday, month, year;

  66.     (void) memset(&tm, 0, sizeof(tm));
  67.     sec = min = hour = mday = month = year = 0;

  68.     if (((sscanf(s, "%d/%3s/%d %d:%d:%d",&mday, mon, &year, &hour, &min, &sec) == 6) ||
  69.      (sscanf(s, "%d %3s %d %d:%d:%d",&mday, mon, &year, &hour, &min, &sec) == 6) ||
  70.      (sscanf(s, "%*3s, %d %3s %d %d:%d:%d", &mday, mon, &year, &hour, &min, &sec) == 6) ||
  71.      (sscanf(s, "%d-%3s-%d %d:%d:%d",&mday, mon, &year, &hour, &min, &sec) == 6)) && (month = montoi(mon)) != -1)
  72.     {
  73.         tm.tm_mday    = mday;
  74.         tm.tm_mon    = month;
  75.         tm.tm_year    = year;
  76.         tm.tm_hour    = hour;
  77.         tm.tm_min    = min;
  78.         tm.tm_sec    = sec;
  79.     }

  80.     if (tm.tm_year > 1900)
  81.         tm.tm_year -= 1900;
  82.     else if (tm.tm_year < 70)
  83.         tm.tm_year += 100;

  84.     DBGPRINT("LCW<==date_to_epoch\n");
  85.     return (mktime(&tm));
  86. }
  87. /******************************************************
  88. 函数名:Request_HeaderParse(char *s, int len, struct headers *parsed)
  89. 参数:
  90. 功能:
  91. *******************************************************/
  92. void Request_HeaderParse(char *s, int len, struct headers *parsed)
  93. {
  94.     DBGPRINT("LCW==>Request_HeaderParse\n");
  95.     struct http_header *h;//结构struct http_header指针
  96.     union variant *v;//通用参数
  97.     char *p,*e = s + len;//p当前位置,e尾部
  98.     // 查找请求字符串中的头部关键字
  99.     while (s < e)
  100.     {
  101.         for (p = s; p < e && *p != '\n'; ) //查找一行末尾
  102.         {
  103.             p++;
  104.         }
  105.         for (h = http_headers; h->len != 0; h++)//已知方法
  106.         { //最上面定义的那个结构体数组
  107.             if (e - s > h->len && !strncasecmp(s, h->name, h->len))//字符串匹配
  108.             {
  109.                 break;
  110.             }
  111.         }
  112.         if (h->len != 0) //将此方法放入
  113.         {
  114.             s += h->len;//请求字符串中值的位置
  115.             v = (union variant *) ((char *) parsed + h->offset);//将值存放到参数parsed中
  116.             // 根据头部选项不同,计算不同的值*/
  117.             if (h->type == HDR_STRING) //字符串类型
  118.             {
  119.                 v->v_vec.ptr = s;//字符串开始
  120.                 v->v_vec.len = p - s;//字符串长度
  121.                 if (p[-1] == '\r' && v->v_vec.len > 0)
  122.                 {
  123.                     v->v_vec.len--;
  124.                 }
  125.             }
  126.             else if (h->type == HDR_INT) //INT类型
  127.             {
  128.                 v->v_big_int = strtoul(s, NULL, 10);
  129.             }
  130.             else if (h->type == HDR_DATE) //时间格式
  131.             {
  132.                 v->v_time = date_to_epoch(s);
  133.             }
  134.         }

  135.         s = p + 1;//转到下一个头部
  136.     }
  137.     DBGPRINT("LCW<==Request_HeaderParse\n");
  138. }
  139. #define JUMPOVER_CHAR(p,over) do{for(;*p== over;p++);}while(0);
  140. #define JUMPTO_CHAR(p,to) do{for(;* to;p++);}while(0);
  141. /******************************************************
  142. 函数名:Request_Parse(struct worker_ctl *wctl)
  143. 参数:
  144. 功能:分析获得的请求
  145. *******************************************************/
  146. int Request_Parse(struct worker_ctl *wctl)
  147. {
  148.     DBGPRINT("LCW==>Request_Parse\n");
  149.     struct worker_conn *c = &wctl->conn;
  150.     struct conn_request *req = &c->con_req;
  151.     struct conn_response *res = &c->con_res;
  152.     int retval = 200;
  153.     char *p = req->req.ptr;
  154.     int len = req->req.len;
  155.     char *pos = NULL;
  156.     //处理第一行
  157.     //[GET /root/default.html HTTP/1.1\r\n]*/
  158.     //查找一行末尾
  159.     pos = memchr(p, '\n', len);
  160.     if(*(pos-1) == '\r')
  161.     {
  162.         *(pos-1) = '\0';
  163.     }
  164.     *pos = '\0';
  165.     pos = p;
  166.     //方法    
  167.     int found = 0;
  168.     JUMPOVER_CHAR(pos,' ');//跳过空格
  169.     struct vec *m= NULL;
  170.     //查找比较方法字符串
  171.     for(m = &_shttpd_methods[0];m->ptr!=NULL;m++)
  172.     {
  173.         if(!strncmp(m->ptr, pos, m->len))//比较字符串
  174.         {
  175.             req->method = m->type;//更新头部方法
  176.             found = 1;
  177.             break;
  178.         }
  179.     }
  180.     if(!found)
  181.     {
  182.         retval = 400;
  183.         goto EXITRequest_Parse;
  184.     }

  185.     //URI分析*/
  186.     pos += m->len;//跳过方法
  187.     JUMPOVER_CHAR(pos,' ');//跳过空格
  188.     len -= pos -p;
  189.     p = pos;
  190.     JUMPTO_CHAR(pos, ' ');//跳到空格
  191.     *pos = '\0';
  192.     req->uri = (char*)p;
  193.     //文件
  194.     snprintf(req->rpath, URI_MAX, "%s/%s",conf_para.DocumentRoot, req->uri);
  195.     res->fd = open(req->rpath, O_RDONLY , 0644);
  196.     if(res->fd != -1)
  197.     {
  198.         fstat(res->fd, &res->fsate);    
  199.         if(S_ISDIR(res->fsate.st_mode))
  200.         {
  201.             retval = 403;
  202.             goto EXITRequest_Parse;
  203.         }
  204.     }
  205.     else
  206.     {
  207.         
  208.         retval = 404;
  209.         goto EXITRequest_Parse;
  210.     }
  211.         
  212.     //HTTP版本:
  213.     //    HTTP/[1|0].[1|0|9]
  214.     pos += 1;
  215.     JUMPOVER_CHAR(pos,' ');//跳过空格
  216.     len -= pos -p;
  217.     p = pos;
  218.     sscanf(p,"HTTP/%lu.%lu",&req->major, &req->minor);
  219.     if(!((req->major == 0 && req->minor == 9)||(req->major == 1 && req->minor == 0)||(req->major == 1 && req->minor == 1)))
  220.     {
  221.         retval = 505;
  222.         goto EXITRequest_Parse;
  223.     }
  224.     //其他头部信息
  225.     JUMPTO_CHAR(pos, '\0');
  226.     JUMPOVER_CHAR(pos,'\0');//跳过空字符
  227.     len -= pos - p;
  228.     p = pos;
  229.     Request_HeaderParse(p, len, & req->ch);    
  230.     DBGPRINT("URI:'%s',patch:'%s'\n",req->uri,req->rpath);
  231. EXITRequest_Parse:
  232.     DBGPRINT("LCW<==Request_Parse\n");
  233.     return retval;
  234. }
  235. /******************************************************
  236. 函数名:Request_Handle(struct worker_ctl* wctl)
  237. 参数:
  238. 功能:处理并响应客户端请求
  239. *******************************************************/
  240. int Request_Handle(struct worker_ctl* wctl)
  241. {
  242.     DBGPRINT("LCW==>Request_Handle\n");
  243.     int err = wctl->conn.con_req.err;        
  244.     int cs = wctl->conn.cs;
  245.     int cl = -1;
  246.     char *ptr = wctl->conn.con_res.res.ptr;
  247.     int len = -1;
  248.     int n = -1;
  249.     switch(err)
  250.     {
  251.         case 200:
  252.             Method_Do(wctl);
  253.             int fd = wctl->conn.con_res.fd;
  254.             cl = wctl->conn.con_res.cl;
  255.             len = strlen(wctl->conn.con_res.res.ptr);
  256.             n = write(cs, ptr, len);
  257.             printf("echo header:%s, write to client %d bytes, status:%d\n",ptr,n,wctl->conn.con_res.status);
  258.             if(fd != -1)
  259.             {        
  260.                 lseek(fd, 0, SEEK_SET);
  261.                 len = sizeof(wctl->conn.dres);
  262.                 printf("response len:%d, content length:%d\n",len,wctl->conn.con_res.cl);
  263.                 for(n = 0; cl>0; cl -= n)
  264.                 {
  265.                     n = read(fd,ptr,len>cl?cl:sizeof(wctl->conn.dres));
  266.                     printf("read %d bytes,",n);
  267.                     if(n > 0)
  268.                     {
  269.                         n =write(cs, ptr, n);
  270.                         printf("write %d bytes\n",n);
  271.                     }
  272.                 }
  273.                 close(fd);
  274.                 wctl->conn.con_res.fd = -1;
  275.             }

  276.             break;
  277.         default:
  278.         case 400:
  279.             Error_400(wctl);
  280.             cl = wctl->conn.con_res.cl;
  281.             len = strlen(wctl->conn.con_res.res.ptr);        
  282.             n = write(cs, ptr, len);            
  283.             break;    
  284.         case 403:
  285.             Error_403(wctl);
  286.             cl = wctl->conn.con_res.cl;
  287.             len = strlen(wctl->conn.con_res.res.ptr);        
  288.             n = write(cs, ptr, len);            
  289.             break;    
  290.         case 404:
  291.             Error_404(wctl);
  292.             cl = wctl->conn.con_res.cl;
  293.             len = strlen(wctl->conn.con_res.res.ptr);    
  294.             n = write(cs, ptr, len);            
  295.             break;    
  296.         case 505:
  297.             Error_505(wctl);
  298.             cl = wctl->conn.con_res.cl;
  299.             len = strlen(wctl->conn.con_res.res.ptr);        
  300.             n = write(cs, ptr, len);            
  301.             break;            
  302.     }
  303.     DBGPRINT("LCW<==Request_Handle\n");
  304.     return 0;
  305. }

阅读(1199) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~