patch-2.3.14 linux/net/khttpd/datasending.c
Next file: linux/net/khttpd/logging.c
Previous file: linux/net/khttpd/accept.c
Back to the patch index
Back to the overall index
- Lines: 195
- Date:
Wed Aug 18 09:49:42 1999
- Orig file:
v2.3.13/linux/net/khttpd/datasending.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.3.13/linux/net/khttpd/datasending.c linux/net/khttpd/datasending.c
@@ -0,0 +1,194 @@
+/*
+
+kHTTPd -- the next generation
+
+Send actual file-data to the connections
+
+*/
+/****************************************************************
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ ****************************************************************/
+
+/*
+
+Purpose:
+
+DataSending does the actual sending of file-data to the socket.
+
+Note: Since asynchronous reads do not -yet- exists, this might block!
+
+Return value:
+ The number of requests that changed status (ie: made some progress)
+*/
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+#include <net/tcp.h>
+
+#include <asm/uaccess.h>
+#include <linux/smp_lock.h>
+
+#include "structure.h"
+#include "prototypes.h"
+
+static char *Block[CONFIG_KHTTPD_NUMCPU];
+
+
+int DataSending(const int CPUNR)
+{
+ struct http_request *CurrentRequest,**Prev;
+ int count = 0;
+
+ EnterFunction("DataSending");
+
+ Prev = &(threadinfo[CPUNR].DataSendingQueue);
+ CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
+ while (CurrentRequest!=NULL)
+ {
+ int ReadSize,Space;
+ int retval;
+ mm_segment_t oldfs;
+
+
+ /* First, test if the socket has any buffer-space left.
+ If not, no need to actually try to send something. */
+
+
+ Space=4096;
+ if (CurrentRequest->sock->sk!=NULL)
+ {
+ lock_sock(CurrentRequest->sock->sk);
+ Space = sock_wspace(CurrentRequest->sock->sk);
+ release_sock(CurrentRequest->sock->sk);
+ }
+
+ ReadSize = min(4096,CurrentRequest->FileLength - CurrentRequest->BytesSent);
+ ReadSize = min(ReadSize , Space );
+
+ if (ReadSize>0)
+ {
+ /* This part does a redundant data-copy. To bad for now.
+ In the future, we might want to nick the data right out
+ of the page-cache
+ */
+
+ CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
+
+ oldfs = get_fs(); set_fs(KERNEL_DS);
+ retval = CurrentRequest->filp->f_op->read(CurrentRequest->filp, Block[CPUNR], ReadSize, &CurrentRequest->filp->f_pos);
+ set_fs(oldfs);
+
+ if (retval>0)
+ {
+ retval = SendBuffer_async(CurrentRequest->sock,Block[CPUNR],(size_t)retval);
+ if (retval>0)
+ {
+ CurrentRequest->BytesSent += retval;
+ count++;
+
+ }
+ }
+
+ }
+ lock_sock(CurrentRequest->sock->sk);
+
+ /*
+ If end-of-file or closed connection: Finish this request
+ by moving it to the "logging" queue.
+ */
+ if ((CurrentRequest->BytesSent>=CurrentRequest->FileLength)||
+ (CurrentRequest->sock->sk->state !=TCP_ESTABLISHED))
+ {
+ struct http_request *Next;
+ Next = CurrentRequest->Next;
+
+ if (CurrentRequest->sock->sk->state ==TCP_ESTABLISHED)
+ {
+
+ CurrentRequest->sock->sk->nonagle = 0;
+ CurrentRequest->sock->sk->linger = 0;
+ tcp_push_pending_frames(CurrentRequest->sock->sk,&(CurrentRequest->sock->sk->tp_pinfo.af_tcp));
+ }
+
+ release_sock(CurrentRequest->sock->sk);
+
+
+
+ (*Prev) = CurrentRequest->Next;
+
+ CurrentRequest->Next = threadinfo[CPUNR].LoggingQueue;
+ threadinfo[CPUNR].LoggingQueue = CurrentRequest;
+
+ CurrentRequest = Next;
+ continue;
+
+ }
+ release_sock(CurrentRequest->sock->sk);
+
+
+ Prev = &(CurrentRequest->Next);
+ CurrentRequest = CurrentRequest->Next;
+ }
+
+ LeaveFunction("DataSending");
+ return count;
+}
+
+int InitDataSending(int ThreadCount)
+{
+ int I,I2;
+
+ EnterFunction("InitDataSending");
+ I=0;
+ while (I<ThreadCount)
+ {
+ Block[I] = (char*)get_free_page((int)GFP_KERNEL);
+ if (Block[I] == NULL)
+ {
+ I2=0;
+ while (I2<I-1)
+ {
+ free_page((unsigned long)Block[I2++]);
+ }
+ LeaveFunction("InitDataSending - abort");
+ return -1;
+ }
+ I++;
+ }
+ LeaveFunction("InitDataSending");
+ return 0;
+}
+
+void StopDataSending(const int CPUNR)
+{
+ struct http_request *CurrentRequest,*Next;
+
+ EnterFunction("StopDataSending");
+ CurrentRequest = threadinfo[CPUNR].DataSendingQueue;
+
+ while (CurrentRequest!=NULL)
+ {
+ Next = CurrentRequest->Next;
+ CleanUpRequest(CurrentRequest);
+ CurrentRequest=Next;
+ }
+
+ threadinfo[CPUNR].DataSendingQueue = NULL;
+
+ free_page( (unsigned long)Block[CPUNR]);
+ LeaveFunction("StopDataSending");
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)