OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [khttpd/] [datasending.c] - Rev 1774

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 
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/config.h>
#include <linux/kernel.h>
#include <linux/locks.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];
 
/*
 
This send_actor is for use with do_generic_file_read (ie sendfile())
It sends the data to the socket indicated by desc->buf.
 
*/
static int sock_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size)
{
	int written;
	char *kaddr;
	unsigned long count = desc->count;
	struct socket *sock = (struct socket *) desc->buf;
	mm_segment_t old_fs;
 
	if (size > count)
		size = count;
	old_fs = get_fs();
	set_fs(KERNEL_DS);
 
	kaddr = kmap(page);
	written = SendBuffer_async(sock, kaddr + offset, size);
	kunmap(page);
	set_fs(old_fs);
	if (written < 0) {
		desc->error = written;
		written = 0;
	}
	desc->count = count - written;
	desc->written += written;
	return written;
}
 
 
 
 
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;
 
 
		/* First, test if the socket has any buffer-space left.
		   If not, no need to actually try to send something.  */
 
 
		Space = sock_wspace(CurrentRequest->sock->sk);
 
		ReadSize = min_t(int, 4 * 4096, CurrentRequest->FileLength - CurrentRequest->BytesSent);
		ReadSize = min_t(int, ReadSize, Space);
 
		if (ReadSize>0)
		{			
			struct inode *inode;
 
			inode = CurrentRequest->filp->f_dentry->d_inode;
 
			if (inode->i_mapping->a_ops->readpage) {
				/* This does the actual transfer using sendfile */		
				read_descriptor_t desc;
				loff_t *ppos;
 
				CurrentRequest->filp->f_pos = CurrentRequest->BytesSent;
 
				ppos = &CurrentRequest->filp->f_pos;
 
				desc.written = 0;
				desc.count = ReadSize;
				desc.buf = (char *) CurrentRequest->sock;
				desc.error = 0;
				do_generic_file_read(CurrentRequest->filp, ppos, &desc, sock_send_actor);
				if (desc.written>0)
				{	
					CurrentRequest->BytesSent += desc.written;
					count++;
				}			
			} 
			else  /* FS doesn't support sendfile() */
			{
				mm_segment_t oldfs;
				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++;				
					}
				}
			}
 
		}
 
		/* 
		   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
		     && CurrentRequest->sock->sk->state!=TCP_CLOSE_WAIT))
		{
			struct http_request *Next;
			Next = CurrentRequest->Next;
 
			lock_sock(CurrentRequest->sock->sk);
			if  (CurrentRequest->sock->sk->state == TCP_ESTABLISHED ||
			     CurrentRequest->sock->sk->state == TCP_CLOSE_WAIT)
			{
				CurrentRequest->sock->sk->tp_pinfo.af_tcp.nonagle = 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;
 
		}
 
 
		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");
}
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.