⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 http.c

📁 www工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
/*									 HTTP.c**	MULTITHREADED IMPLEMENTATION OF HTTP CLIENT****	(c) COPYRIGHT MIT 1995.**	Please first read the full copyright statement in the file COPYRIGH.**	@(#) $Id: HTTP.c,v 1.178 1999/02/22 22:10:12 frystyk Exp $****	This module implments the HTTP protocol as a state machine**** History:**    < May 24 94 ??	Unknown - but obviously written**	May 24 94 HF	Made reentrent and cleaned up a bit. Implemented**			Forward, redirection, error handling and referer field**	 8 Jul 94  FM	Insulate free() from _free structure element.**	Jul 94 HFN	Written on top of HTTP.c, Henrik Frystyk***//* Library include files */#include "wwwsys.h"#include "WWWUtil.h"#include "WWWCore.h"#include "HTHeader.h"#include "HTMIMERq.h"#include "HTReqMan.h"#include "HTTPUtil.h"#include "HTTPReq.h"#include "HTTP.h"					       /* Implements *//* Macros and other defines */#ifndef HTTP_PORT#define HTTP_PORT 80	/* Allocated to http by Jon Postel/ISI 24-Jan-92 */#endif#define PUTC(c)		(*me->target->isa->put_character)(me->target, c)#define PUTS(s)		(*me->target->isa->put_string)(me->target, s)#define PUTBLOCK(b, l)	(*me->target->isa->put_block)(me->target, b, l)#define FREE_TARGET	(*me->target->isa->_free)(me->target)#define ABORT_TARGET	(*me->target->isa->abort)(me->target, e)#ifdef HTDEBUG#include "WWWStream.h"#define HTTP_OUTPUT     "w3chttp.out"PRIVATE FILE * htfp = NULL;#endif/* Type definitions and global variables etc. local to this module *//* Final states have negative value */typedef enum _HTTPState {    HTTP_KILL_PIPE	= -4,    HTTP_RECOVER_PIPE	= -3,    HTTP_ERROR		= -2,    HTTP_OK		= -1,    HTTP_BEGIN		= 0,    HTTP_NEED_STREAM,    HTTP_CONNECTED} HTTPState;/* This is the context structure for the this module */typedef struct _http_info {    HTTPState		state;		  /* Current State of the connection */    HTTPState		next;				       /* Next state */    int			result;	     /* Result to report to the after filter */    BOOL		lock;				/* Block for writing */    HTNet *		net;    HTRequest *		request;    HTTimer *		timer;    BOOL		usedTimer;} http_info;#define MAX_STATUS_LEN		100   /* Max nb of chars to check StatusLine */struct _HTStream {    const HTStreamClass *	isa;    HTStream *		  	target;    HTStream *		  	info_target;	/* For 100 codes */    HTRequest *			request;    http_info *			http;    HTEOLState			state;    BOOL			transparent;    BOOL			cont;    char *			version;	     /* Should we save this? */    int				status;    char *			reason;    char 			buffer[MAX_STATUS_LEN+1];    int				buflen;    int				startLen;/* buflen when put_block was called */};struct _HTInputStream {    const HTInputStreamClass *	isa;};/* How long to wait before writing the body in PUT and POST requests */#define DEFAULT_FIRST_WRITE_DELAY	2000#define DEFAULT_SECOND_WRITE_DELAY	3000PRIVATE ms_t HTFirstWriteDelay = DEFAULT_FIRST_WRITE_DELAY;PRIVATE ms_t HTSecondWriteDelay = DEFAULT_SECOND_WRITE_DELAY;#ifdef HT_NO_PIPELININGPRIVATE HTTPConnectionMode ConnectionMode = HTTP_11_NO_PIPELINING;#else#ifdef HT_MUXPRIVATE HTTPConnectionMode ConnectionMode = HTTP_11_MUX;#else#ifdef HT_FORCE_10PRIVATE HTTPConnectionMode ConnectionMode = HTTP_FORCE_10;#elsePRIVATE HTTPConnectionMode ConnectionMode = HTTP_11_PIPELINING;#endif#endif#endif/* ------------------------------------------------------------------------- *//* 			          Help Functions			     *//* ------------------------------------------------------------------------- *//*	HTTPCleanup**	-----------**      This function closes the connection and frees memory.**      Returns YES on OK, else NO*/PRIVATE int HTTPCleanup (HTRequest *req, int status){    HTNet * net = HTRequest_net(req);    http_info * http = (http_info *) HTNet_context(net);    HTStream * input = HTRequest_inputStream(req);    HTTRACE(PROT_TRACE, "HTTP Clean.. Called with status %d, net %p\n" _ status _ net);    if (status == HT_INTERRUPTED) {    	HTAlertCallback * cbf = HTAlert_find(HT_PROG_INTERRUPT);    	if (cbf) (*cbf)(req, HT_PROG_INTERRUPT,	    HT_MSG_NULL, NULL, NULL, NULL);    } else if (status == HT_TIMEOUT) {    	HTAlertCallback * cbf = HTAlert_find(HT_PROG_TIMEOUT);    	if (cbf) (*cbf)(req, HT_PROG_TIMEOUT,	    HT_MSG_NULL, NULL, NULL, NULL);    }	    /* Free stream with data TO network */    if (input) {	if (status==HT_INTERRUPTED || status==HT_RECOVER_PIPE || status==HT_TIMEOUT)	    (*input->isa->abort)(input, NULL);	else	    (*input->isa->_free)(input);	HTRequest_setInputStream(req, NULL);    }    /*    **  Remove if we have registered an upload function as a callback    */    if (http->timer) {	HTTimer_delete(http->timer);	http->timer = NULL;    }    /*    ** Remove the request object and our own context structure for http.    */    if (status != HT_RECOVER_PIPE) {        HTNet_delete(net, status);	HT_FREE(http);    }    return YES;}/***	Informational 1xx codes are handled separately**	Returns YES if we should continue, NO if we should stop*/PRIVATE BOOL HTTPInformation (HTStream * me){    http_info * http = me->http;    switch (me->status) {    case 100:#if 0	HTRequest_addError(me->request, ERR_INFO, NO, HTERR_CONTINUE,			   me->reason, (int) strlen(me->reason),			   "HTTPInformation");#endif	return YES;	break;    case 101:	/*	**  We consider 101 Switching as a final state and exit this request	*/	HTRequest_addError(me->request, ERR_INFO, NO, HTERR_SWITCHING,			   me->reason, (int) strlen(me->reason),			   "HTTPInformation");	http->next = HTTP_OK;	http->result = HT_UPGRADE;	break;    default:	HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_BAD_REPLY,		   (void *) me->buffer, me->buflen, "HTTPNextState");	http->next = HTTP_ERROR;	http->result = HT_ERROR;	break;    }    return NO;}/***	This is a big switch handling all HTTP return codes. It puts in any**	appropiate error message and decides whether we should expect data**	or not.*/PRIVATE void HTTPNextState (HTStream * me){    http_info * http = me->http;    int error_class = me->status / 100;    switch (error_class) {    case 0:							     /* 0.9 response */    case 2:	switch (me->status) {	case 201:							  /* Created */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_CREATED,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_CREATED;	    break;	case 202:							 /* Accepted */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_ACCEPTED,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_ACCEPTED;	    break;	case 203:				    /* Non-authoritative information */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_NON_AUTHORITATIVE,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_LOADED;	    break;	case 204:						      /* No Response */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_NO_CONTENT,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_NO_DATA;	    break;	case 205:						    /* Reset Content */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_RESET,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_RESET_CONTENT;	    break;	case 206:						  /* Partial Content */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_PARTIAL,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_PARTIAL_CONTENT;	    break;	case 207:						/* Partial Update OK */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_PARTIAL_OK,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_PARTIAL_CONTENT;	    break;	default:	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_OK,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_LOADED;	    break;	}	break;    case 3:	switch (me->status) {	case 301:						   	    /* Moved */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_MOVED,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_PERM_REDIRECT;	    break;	case 302:							    /* Found */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_FOUND,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_FOUND;	    break;		case 303:							   /* Method */	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_METHOD,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_SEE_OTHER;	    break;	case 304:						     /* Not Modified */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_NOT_MODIFIED,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_NOT_MODIFIED;	    break;		case 305:						        /* Use proxy */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_USE_PROXY,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_USE_PROXY;	    break;	#if 0	case 306:						        /* Use proxy */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_PROXY_REDIRECT,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_USE_PROXY;	    break;#endif	case 307:						        /* Use proxy */	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_TEMP_REDIRECT,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_TEMP_REDIRECT;	    break;	default:	    HTRequest_addError(me->request, ERR_INFO, NO, HTERR_MULTIPLE,			       me->reason, (int) strlen(me->reason),			       "HTTPNextState");	    http->next = HTTP_OK;	    http->result = HT_LOADED;	    break;	}		break;    case 4:	switch (me->status) {	case 401:	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_UNAUTHORIZED,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_NO_ACCESS;	    break;		case 402:						 /* Payment required */	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_PAYMENT_REQUIRED,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = -402;	    break;		case 403:							/* Forbidden */	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_FORBIDDEN,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_FORBIDDEN;	    break;		case 404:							/* Not Found */	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_NOT_FOUND,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = -404;	    break;		case 405:						      /* Not Allowed */	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_NOT_ALLOWED,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = -405;	    break;	case 406:						  /* None Acceptable */	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_NONE_ACCEPTABLE,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_NOT_ACCEPTABLE;	    break;	case 407:			       	    /* Proxy Authentication Required */	    HTRequest_addError(me->request, ERR_FATAL, NO,HTERR_PROXY_UNAUTHORIZED,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = HT_NO_PROXY_ACCESS;	    break;	case 408:						  /* Request Timeout */	    HTRequest_addError(me->request, ERR_FATAL, NO, HTERR_TIMEOUT,			       me->reason, (int) strlen(me->reason), "HTTPNextState");	    http->next = HTTP_ERROR;	    http->result = -408;	    break;	case 409:						  	 /* Conflict */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -