waitheaders.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2. kHTTPd -- the next generation
  3. Wait for headers on the accepted connections
  4. */
  5. /****************************************************************
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, write to the Free Software
  18.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  ****************************************************************/
  21. /*
  22. Purpose:
  23. WaitForHeaders polls all connections in "WaitForHeaderQueue" to see if
  24. headers have arived. If so, the headers are decoded and the request is
  25. moved to either the "SendingDataQueue" or the "UserspaceQueue".
  26. Return value:
  27. The number of requests that changed status
  28. */
  29. #include <linux/config.h>
  30. #include <linux/kernel.h>
  31. #include <linux/skbuff.h>
  32. #include <linux/smp_lock.h>
  33. #include <linux/file.h>
  34. #include <asm/uaccess.h>
  35. #include "structure.h"
  36. #include "prototypes.h"
  37. static char *Buffer[CONFIG_KHTTPD_NUMCPU];
  38. static int DecodeHeader(const int CPUNR, struct http_request *Request);
  39. int WaitForHeaders(const int CPUNR)
  40. {
  41. struct http_request *CurrentRequest,**Prev;
  42. struct sock *sk;
  43. int count = 0;
  44. EnterFunction("WaitForHeaders");
  45. CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
  46. Prev = &(threadinfo[CPUNR].WaitForHeaderQueue);
  47. while (CurrentRequest!=NULL)
  48. {
  49. /* If the connection is lost, remove from queue */
  50. if (CurrentRequest->sock->sk->state != TCP_ESTABLISHED
  51.     && CurrentRequest->sock->sk->state != TCP_CLOSE_WAIT)
  52. {
  53. struct http_request *Next;
  54. Next = CurrentRequest->Next;
  55. *Prev = CurrentRequest->Next;
  56. CurrentRequest->Next = NULL;
  57. CleanUpRequest(CurrentRequest);
  58. CurrentRequest = Next;
  59. continue;
  60. }
  61. /* If data pending, take action */
  62. sk = CurrentRequest->sock->sk;
  63. if (!skb_queue_empty(&(sk->receive_queue))) /* Do we have data ? */
  64. {
  65. struct http_request *Next;
  66. /* Decode header */
  67. if (DecodeHeader(CPUNR,CurrentRequest)<0)
  68. {
  69. CurrentRequest = CurrentRequest->Next;
  70. continue;
  71. /* Remove from WaitForHeaderQueue */
  72. Next= CurrentRequest->Next;
  73. *Prev = Next;
  74. count++;
  75. /* Add to either the UserspaceQueue or the DataSendingQueue */
  76. if (CurrentRequest->IsForUserspace!=0)
  77. {
  78. CurrentRequest->Next = threadinfo[CPUNR].UserspaceQueue;
  79. threadinfo[CPUNR].UserspaceQueue = CurrentRequest;
  80. } else
  81. {
  82. CurrentRequest->Next = threadinfo[CPUNR].DataSendingQueue;
  83. threadinfo[CPUNR].DataSendingQueue = CurrentRequest;
  84. CurrentRequest = Next;
  85. continue;
  86. }
  87. Prev = &(CurrentRequest->Next);
  88. CurrentRequest = CurrentRequest->Next;
  89. }
  90. LeaveFunction("WaitForHeaders");
  91. return count;
  92. }
  93. void StopWaitingForHeaders(const int CPUNR)
  94. {
  95. struct http_request *CurrentRequest,*Next;
  96. EnterFunction("StopWaitingForHeaders");
  97. CurrentRequest = threadinfo[CPUNR].WaitForHeaderQueue;
  98. while (CurrentRequest!=NULL)
  99. {
  100. Next = CurrentRequest->Next;
  101. CleanUpRequest(CurrentRequest);
  102. CurrentRequest=Next;
  103. }
  104. threadinfo[CPUNR].WaitForHeaderQueue = NULL; /* The queue is empty now */
  105. free_page((unsigned long)Buffer[CPUNR]);
  106. Buffer[CPUNR]=NULL;
  107. EnterFunction("StopWaitingForHeaders");
  108. }
  109. /* 
  110. DecodeHeader peeks at the TCP/IP data, determines what the request is, 
  111. fills the request-structure and sends the HTTP-header when apropriate.
  112. */
  113. static int DecodeHeader(const int CPUNR, struct http_request *Request)
  114. {
  115. struct msghdr msg;
  116. struct iovec iov;
  117. int len;
  118. mm_segment_t oldfs;
  119. EnterFunction("DecodeHeader");
  120. if (Buffer[CPUNR] == NULL) {
  121. /* see comments in main.c regarding buffer managemnet - dank */
  122. printk(KERN_CRIT "khttpd: lost my buffer");
  123. BUG();
  124. }
  125. /* First, read the data */
  126. msg.msg_name     = 0;
  127. msg.msg_namelen  = 0;
  128. msg.msg_iov  = &iov;
  129. msg.msg_iovlen   = 1;
  130. msg.msg_control  = NULL;
  131. msg.msg_controllen = 0;
  132. msg.msg_flags    = 0;
  133. msg.msg_iov->iov_base = &Buffer[CPUNR][0];
  134. msg.msg_iov->iov_len  = (size_t)4095;
  135. len = 0;
  136. oldfs = get_fs(); set_fs(KERNEL_DS);
  137. /* 4095 leaves a "0" to terminate the string */
  138. len = sock_recvmsg(Request->sock,&msg,4095,MSG_PEEK);
  139. set_fs(oldfs);
  140. if (len<0) {
  141. /* WONDERFUL. NO COMMENTS. --ANK */
  142. Request->IsForUserspace = 1;
  143. return 0;
  144. }
  145. if (len>=4094) /* BIG header, we cannot decode it so leave it to userspace */
  146. {
  147. Request->IsForUserspace = 1;
  148. return 0;
  149. }
  150. /* Then, decode the header */
  151. ParseHeader(Buffer[CPUNR],len,Request);
  152. Request->filp = OpenFileForSecurity(Request->FileName);
  153. Request->MimeType = ResolveMimeType(Request->FileName,&Request->MimeLength);
  154. if (Request->MimeType==NULL) /* Unknown mime-type */
  155. {
  156. if (Request->filp!=NULL)
  157. {
  158. fput(Request->filp);
  159. Request->filp = NULL;
  160. }
  161. Request->IsForUserspace = 1;
  162. return 0;
  163. }
  164. if (Request->filp==NULL)
  165. {
  166. Request->IsForUserspace = 1;
  167. return 0;
  168. }
  169. else
  170. {
  171. Request->FileLength = (int)Request->filp->f_dentry->d_inode->i_size;
  172. Request->Time       = Request->filp->f_dentry->d_inode->i_mtime;
  173. Request->IMS_Time   = mimeTime_to_UnixTime(Request->IMS);
  174. sprintf(Request->LengthS,"%i",Request->FileLength);
  175. time_Unix2RFC(min_t(unsigned int, Request->Time,CurrentTime_i),Request->TimeS);
  176.             /* The min() is required by rfc1945, section 10.10:
  177.                It is not allowed to send a filetime in the future */
  178. if (Request->IMS_Time>Request->Time)
  179. { /* Not modified since last time */
  180. Send304(Request->sock);
  181. Request->FileLength=0;
  182. }
  183. else   /* Normal Case */
  184. {
  185. Request->sock->sk->tp_pinfo.af_tcp.nonagle = 2; /* this is TCP_CORK */
  186. if (Request->HTTPVER!=9)  /* HTTP/0.9 doesn't allow a header */
  187. SendHTTPHeader(Request);
  188. }
  189. }
  190. LeaveFunction("DecodeHeader");
  191. return 0;
  192. }
  193. int InitWaitHeaders(int ThreadCount)
  194. {
  195. int I,I2;
  196. EnterFunction("InitWaitHeaders");
  197. I=0;
  198. while (I<ThreadCount)
  199. {
  200. Buffer[I] = (char*)get_free_page((int)GFP_KERNEL);
  201. if (Buffer[I] == NULL) 
  202. {
  203. printk(KERN_CRIT "kHTTPd: Not enough memory for basic needsn");
  204. I2=0;
  205. while (I2<I-1)
  206. {
  207. free_page( (unsigned long)Buffer[I2++]);
  208. }
  209. return -1;
  210. }
  211. I++;
  212. }
  213. LeaveFunction("InitWaitHeaders");
  214. return 0;
  215. }