datasending.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:6k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2. kHTTPd -- the next generation
  3. Send actual file-data to the 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. DataSending does the actual sending of file-data to the socket.
  24. Note: Since asynchronous reads do not -yet- exists, this might block!
  25. Return value:
  26. The number of requests that changed status (ie: made some progress)
  27. */
  28. #include <linux/config.h>
  29. #include <linux/kernel.h>
  30. #include <linux/locks.h>
  31. #include <linux/skbuff.h>
  32. #include <net/tcp.h>
  33. #include <asm/uaccess.h>
  34. #include <linux/smp_lock.h>
  35. #include "structure.h"
  36. #include "prototypes.h"
  37. static char *Block[CONFIG_KHTTPD_NUMCPU];
  38. /*
  39. This send_actor is for use with do_generic_file_read (ie sendfile())
  40. It sends the data to the socket indicated by desc->buf.
  41. */
  42. static int sock_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
  43. {
  44. int written;
  45. char *kaddr;
  46. unsigned long count = desc->count;
  47. struct socket *sock = (struct socket *) desc->buf;
  48. mm_segment_t old_fs;
  49. if (size > count)
  50. size = count;
  51. old_fs = get_fs();
  52. set_fs(KERNEL_DS);
  53. kaddr = kmap(page);
  54. written = SendBuffer_async(sock, kaddr + offset, size);
  55. kunmap(page);
  56. set_fs(old_fs);
  57. if (written < 0) {
  58. desc->error = written;
  59. written = 0;
  60. }
  61. desc->count = count - written;
  62. desc->written += written;
  63. return written;
  64. }
  65. int DataSending(const int CPUNR)
  66. {
  67. struct http_request *CurrentRequest,**Prev;
  68. int count = 0;
  69. EnterFunction("DataSending");
  70. Prev = &(threadinfo[CPUNR].DataSendingQueue);
  71. CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
  72. while (CurrentRequest!=NULL)
  73. {
  74. int ReadSize,Space;
  75. int retval;
  76. /* First, test if the socket has any buffer-space left.
  77.    If not, no need to actually try to send something.  */
  78.   
  79. Space = sock_wspace(CurrentRequest->sock->sk);
  80. ReadSize = min_t(int, 4 * 4096, CurrentRequest->FileLength - CurrentRequest->BytesSent);
  81. ReadSize = min_t(int, ReadSize, Space);
  82. if (ReadSize>0)
  83. {
  84. struct inode *inode;
  85. inode = CurrentRequest->filp->f_dentry->d_inode;
  86. if (inode->i_mapping->a_ops->readpage) {
  87. /* This does the actual transfer using sendfile */
  88. read_descriptor_t desc;
  89. loff_t *ppos;
  90. CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
  91. ppos = &CurrentRequest->filp->f_pos;
  92. desc.written = 0;
  93. desc.count = ReadSize;
  94. desc.buf = (char *) CurrentRequest->sock;
  95. desc.error = 0;
  96. do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor);
  97. if (desc.written>0)
  98. {
  99. CurrentRequest->BytesSent += desc.written;
  100. count++;
  101. }
  102. else  /* FS doesn't support sendfile() */
  103. {
  104. mm_segment_t oldfs;
  105. CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
  106. oldfs = get_fs(); set_fs(KERNEL_DS);
  107. retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos);
  108. set_fs(oldfs);
  109. if (retval>0)
  110. {
  111. retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval);
  112. if (retval>0)
  113. {
  114. CurrentRequest->BytesSent += retval;
  115. count++;
  116. }
  117. }
  118. }
  119. }
  120. /* 
  121.    If end-of-file or closed connection: Finish this request 
  122.    by moving it to the "logging" queue. 
  123. */
  124. if ((CurrentRequest->BytesSent>=CurrentRequest->FileLength)||
  125.     (CurrentRequest->sock->sk->state!=TCP_ESTABLISHED
  126.      && CurrentRequest->sock->sk->state!=TCP_CLOSE_WAIT))
  127. {
  128. struct http_request *Next;
  129. Next = CurrentRequest->Next;
  130. lock_sock(CurrentRequest->sock->sk);
  131. if  (CurrentRequest->sock->sk->state == TCP_ESTABLISHED ||
  132.      CurrentRequest->sock->sk->state == TCP_CLOSE_WAIT)
  133. {
  134. CurrentRequest->sock->sk->tp_pinfo.af_tcp.nonagle = 0;
  135. tcp_push_pending_frames(CurrentRequest->sock->sk,&(CurrentRequest->sock->sk->tp_pinfo.af_tcp));
  136. }
  137. release_sock(CurrentRequest->sock->sk);
  138. (*Prev) = CurrentRequest->Next;
  139. CurrentRequest->Next = threadinfo[CPUNR].LoggingQueue;
  140. threadinfo[CPUNR].LoggingQueue = CurrentRequest;
  141. CurrentRequest = Next;
  142. continue;
  143. }
  144. Prev = &(CurrentRequest->Next);
  145. CurrentRequest = CurrentRequest->Next;
  146. }
  147. LeaveFunction("DataSending");
  148. return count;
  149. }
  150. int InitDataSending(int ThreadCount)
  151. {
  152. int I,I2;
  153. EnterFunction("InitDataSending");
  154. I=0;
  155. while (I<ThreadCount)
  156. {
  157. Block[I] = (char*)get_free_page((int)GFP_KERNEL);
  158. if (Block[I] == NULL) 
  159. {
  160. I2=0;
  161. while (I2<I-1)
  162. {
  163. free_page((unsigned long)Block[I2++]);
  164. }
  165. LeaveFunction("InitDataSending - abort");
  166. return -1;
  167. }
  168. I++;
  169. }
  170. LeaveFunction("InitDataSending");
  171. return 0;
  172. }
  173. void StopDataSending(const int CPUNR)
  174. {
  175. struct http_request *CurrentRequest,*Next;
  176. EnterFunction("StopDataSending");
  177. CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
  178. while (CurrentRequest!=NULL)
  179. {
  180. Next = CurrentRequest->Next;
  181. CleanUpRequest(CurrentRequest);
  182. CurrentRequest=Next;
  183. }
  184. threadinfo[CPUNR].DataSendingQueue = NULL;
  185. free_page( (unsigned long)Block[CPUNR]);
  186. LeaveFunction("StopDataSending");
  187. }