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

📄 http.c

📁 www工具包
💻 C
📖 第 1 页 / 共 3 页
字号:
PRIVATE int HTTPStatus_flush (HTStream * me){    return (*me->target->isa->flush)(me->target);}PRIVATE int HTTPStatus_free (HTStream * me){    int status = HT_OK;    if (me->target) {	if ((status = (*me->target->isa->_free)(me->target))==HT_WOULD_BLOCK)	    return HT_WOULD_BLOCK;    }    HT_FREE(me);    return status;}PRIVATE int HTTPStatus_abort (HTStream * me, HTList * e){    if (me->target)	ABORT_TARGET;    HT_FREE(me);    HTTRACE(PROT_TRACE, "HTTPStatus.. ABORTING...\n");    return HT_ERROR;}/*	HTTPStatus Stream**	-----------------*/PRIVATE const HTStreamClass HTTPStatusClass ={		    "HTTPStatus",    HTTPStatus_flush,    HTTPStatus_free,    HTTPStatus_abort,    HTTPStatus_put_character,    HTTPStatus_put_string,    HTTPStatus_put_block};PUBLIC HTStream * HTTPStatus_new (HTRequest *	request,				  void *	param,				  HTFormat	input_format,				  HTFormat	output_format,				  HTStream *	output_stream){    HTStream * me;    if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)        HT_OUTOFMEM("HTTPStatus_new");    me->isa = &HTTPStatusClass;    if (request) {	HTNet * net = HTRequest_net(request);        /* Get existing copy */	http_info * http = (http_info *) HTNet_context(net);	me->request = request;	me->http = http;	http->next = HTTP_ERROR;	me->state = EOL_BEGIN;	return me;    } else	return HTErrorStream();}/* ------------------------------------------------------------------------- *//*		Load Document from HTTP Server			     HTLoadHTTP**		==============================****	Given a hypertext address, this routine loads a document.**** On entry,**      request		This is the request structure**	returns		HT_ERROR	Error has occured in call back**			HT_OK		Call back was OK*/PRIVATE int HTTPEvent (SOCKET soc, void * pVoid, HTEventType type);PUBLIC int HTLoadHTTP (SOCKET soc, HTRequest * request){    http_info *http;			    /* Specific protocol information */    HTParentAnchor *anchor = HTRequest_anchor(request);    HTNet * net = HTRequest_net(request);    /*    ** Initiate a new http structure and bind to request structure    ** This is actually state HTTP_BEGIN, but it can't be in the state    ** machine as we need the structure first.    */    HTTRACE(PROT_TRACE, "HTTP........ Looking for `%s\'\n" _ 			    HTAnchor_physical(anchor));    if ((http = (http_info *) HT_CALLOC(1, sizeof(http_info))) == NULL)      HT_OUTOFMEM("HTLoadHTTP");    http->net = net;    http->request = request;    HTNet_setContext(net, http);    HTNet_setEventCallback(net, HTTPEvent);    HTNet_setEventParam(net, http);  /* callbacks get http* */    return HTTPEvent(soc, http, HTEvent_BEGIN);	    /* get it started - ops is ignored */}PRIVATE int FlushPutEvent (HTTimer * timer, void * param, HTEventType type){    http_info * http = (http_info *) param;    HTStream * input = HTRequest_inputStream(http->request);    HTPostCallback * pcbf = HTRequest_postCallback(http->request);    http->usedTimer = YES;    if (timer != http->timer)	HTDEBUGBREAK("HTTP timer %p not in sync\n" _ timer);    HTTRACE(PROT_TRACE, "Uploading... Flushing %p with timer %p\n" _ http _ timer);    /*    **  We ignore the return code here which we shouldn't!!!    */    if (http && input && pcbf) (*pcbf)(http->request, input);    /*    **  Delete the timer    */    HTTimer_delete(http->timer);    http->timer = NULL;    return HT_OK;}PRIVATE int HTTPEvent (SOCKET soc, void * pVoid, HTEventType type){    http_info * http = (http_info *)pVoid;    int status = HT_ERROR;    HTNet * net = http->net;    HTRequest * request = HTNet_request(net);    HTParentAnchor * anchor = HTRequest_anchor(request);    HTHost * host = HTNet_host(net);    /*    **  Check whether we have been interrupted or timed out    */    if (type == HTEvent_BEGIN) {	http->next = HTTP_OK;	http->result = HT_ERROR;    } else if (type == HTEvent_CLOSE) {	HTRequest_addError(request, ERR_FATAL, NO, HTERR_INTERRUPTED,			   NULL, 0, "HTLoadHTTP");	HTTPCleanup(request, HT_INTERRUPTED);	return HT_OK;    } else if (type == HTEvent_TIMEOUT) {	HTRequest_addError(request, ERR_FATAL, NO, HTERR_TIME_OUT,			   NULL, 0, "HTLoadHTTP");	HTTPCleanup(request, HT_TIMEOUT);	return HT_OK;    } else if (type == HTEvent_END) {	HTTPCleanup(request, http->result);	return HT_OK;    } else if (type == HTEvent_RESET) {	HTTPCleanup(request, HT_RECOVER_PIPE);	http->state = HTTP_BEGIN;	return HT_OK;    }    /* Now jump into the machine. We know the state from the previous run */    while (1) {	switch (http->state) {	case HTTP_BEGIN:	    status = HTHost_connect(host, net, HTAnchor_physical(anchor), HTTP_PORT);	    host = HTNet_host(net);            if (status == HT_OK) {		/*		**  Check the protocol class to see if we have connected to a		**  the right class of server, in this case HTTP. If we don't 		**  know the server then assume a HTTP/1.0		*/		{		    char * s_class = HTHost_class(host);		    if (!s_class) {			if (HTRequest_proxy(request) == NULL) {			    HTAssocList * alist = HTRequest_connection(request);			    if (!(alist && HTAssocList_findObject(alist, "close")))				HTRequest_addConnection(request, "Keep-Alive", "");			}			HTHost_setClass(host, "http");		    } else if (strcasecomp(s_class, "http")) {			HTRequest_addError(request, ERR_FATAL, NO, HTERR_CLASS,					   NULL, 0, "HTLoadHTTP");			http->state = HTTP_ERROR;			break;		    }		}		if (ConnectionMode & HTTP_11_NO_PIPELINING) {		    HTTRACE(PROT_TRACE, "HTTP........ Mode is HTTP/1.1 WITH NO PIPELINING\n");		    HTRequest_setFlush(request, YES);		} else if (ConnectionMode & HTTP_FORCE_10) {		    HTTRACE(PROT_TRACE, "HTTP........ Mode is FORCE HTTP/1.0\n");		    HTHost_setVersion(host, HTTP_10);		}		if (HTNet_preemptive(net)) {		    HTTRACE(PROT_TRACE, "HTTP........ Force flush on preemptive load\n");		    HTRequest_setFlush(request, YES);		}		/* Jump to next state */		http->state = HTTP_NEED_STREAM;	    } else if (status == HT_WOULD_BLOCK || status == HT_PENDING) {		return HT_OK;	    } else if (status == HT_NO_HOST) {		http->result = HT_NO_HOST;		http->state = HTTP_ERROR;	    } else			http->state = HTTP_ERROR;	       /* Error or interrupt */	    break;	    	case HTTP_NEED_STREAM:	    /* 	    ** Create the stream pipe FROM the channel to the application.	    ** The target for the input stream pipe is set up using the	    ** stream stack.	    */	    {            /*            **  during a recovery, we might keep the same HTNet object.            **  if so, reuse it's read stream             */	    HTStream * me = HTNet_readStream( net );            if ( me == NULL ) {                me = HTStreamStack(WWW_HTTP,				   HTRequest_outputFormat(request),				   HTRequest_outputStream(request),				   request, YES);#ifdef HTDEBUG		if (PROT_TRACE) {		    if (!htfp) htfp = fopen(HTTP_OUTPUT, "ab");		    if (htfp) {			me = HTTee(me, HTFWriter_new(request, htfp, YES), NULL);			HTTRACE(PROT_TRACE, "HTTP........ Dumping response to `%s\'\n" _ HTTP_OUTPUT);		    }		}#endif /* HTDEBUG */		HTNet_setReadStream(net, me);            }            HTRequest_setOutputConnected(request, YES);	    }	    /*	    ** Create the stream pipe TO the channel from the application	    ** and hook it up to the request object	    */	    {		HTChannel * channel = HTHost_channel(host);		HTOutputStream * output = HTChannel_getChannelOStream(channel);		int version = HTHost_version(host);		HTStream * app = NULL;		#ifdef HTDEBUG		if (PROT_TRACE) {		    if (!htfp) htfp = fopen(HTTP_OUTPUT, "ab");		    if (htfp) {			output = (HTOutputStream *)			    HTTee((HTStream *) output, HTFWriter_new(request, htfp, YES), NULL);			HTTRACE(PROT_TRACE, "HTTP........ Dumping request to `%s\'\n" _ HTTP_OUTPUT);		    }		}	#endif /* HTDEBUG */		app = HTMethod_hasEntity(HTRequest_method(request)) ?		    HTMIMERequest_new(request,				      HTTPRequest_new(request, (HTStream *) output, NO,						      version),				      YES) :		    HTTPRequest_new(request, (HTStream *) output, YES, version);		HTRequest_setInputStream(request, app);	    }	    /*	    ** Set up concurrent read/write if this request isn't the	    ** source for a PUT or POST. As source we don't start reading	    ** before all destinations are ready. If destination then	    ** register the input stream and get ready for read	    */	    if (HTRequest_isDestination(request)) {		HTHost_register(host, net, HTEvent_READ);		HTRequest_linkDestination(request);	    }	    http->state = HTTP_CONNECTED;	    type = HTEvent_WRITE;			    /* fresh, so try a write */	    break;	    /* As we can do simultanous read and write this is now one state */	  case HTTP_CONNECTED:	      if (type == HTEvent_WRITE) {		  HTStream * input = HTRequest_inputStream(request);		  HTPostCallback * pcbf = HTRequest_postCallback(request);		  status = HTRequest_flush(request) ?		      HTHost_forceFlush(host) : (*input->isa->flush)(input);		  /*		  **  Check to see if we are uploading something or just a normal		  **  GET kind of thing.		  */		  if (pcbf) {		      if (http->lock == NO) {			  int retrys = HTRequest_retrys(request);			  ms_t delay = retrys > 3 ? HTSecondWriteDelay : HTFirstWriteDelay;			  if (!http->timer && !http->usedTimer) {			      http->timer = HTTimer_new(NULL, FlushPutEvent,							http, delay, YES, NO);			      HTTRACE(PROT_TRACE, "Uploading... Holding %p for %lu ms using time %p\n" _ 					  http _ delay _ http->timer);			      HTHost_register(host, net, HTEvent_READ);			  }			  http->lock = YES;		      }		      type = HTEvent_READ;		  } else {		      /*		      **  Check to see if we can start a new request		      **  pending in the host object.		      */		      HTHost_launchPending(host);		      type = HTEvent_READ;		  }		  /* Now check the status code */		  if (status == HT_WOULD_BLOCK)		      return HT_OK;		  else if (status == HT_PAUSE || status == HT_LOADED) {		      type = HTEvent_READ;		  } else if (status==HT_ERROR)		      http->state = HTTP_RECOVER_PIPE;	      } else if (type == HTEvent_FLUSH) {		  HTStream * input = HTRequest_inputStream(request);		  if (input == NULL)		      return HT_ERROR;		  return (*input->isa->flush)(input);	      } else if (type == HTEvent_READ) {		  status = HTHost_read(host, net);		  if (status == HT_WOULD_BLOCK)		      return HT_OK;		  else if (status == HT_CONTINUE) {		      HTTRACE(PROT_TRACE, "HTTP........ Continuing\n");		      http->lock = NO;		      continue;		  } else if (status==HT_LOADED)		      http->state = http->next;	/* Jump to next state (OK or ERROR) */		  else if (status==HT_CLOSED)		      http->state = HTTP_RECOVER_PIPE;		  else if (status == HT_ERROR)		      http->state = HTTP_KILL_PIPE;		  else		      http->state = HTTP_ERROR;	      } else {		  http->state = HTTP_ERROR;	/* don't know how to handle OOB */	      }	      break;	  case HTTP_OK:	    HTTPCleanup(request, http->result);	    return HT_OK;	    break;          case HTTP_RECOVER_PIPE:	  {	      /*	      ** If this is a persistent connection and we get a close	      ** then it is an error and we should recover from it by	      ** restarting the pipe line of requests if any	      */	      if (HTHost_isPersistent(host) && !HTHost_closeNotification(host)) {		  if (host == NULL) return HT_ERROR;		  HTRequest_setFlush(request, YES);		  HTHost_recoverPipe(host);		  return HT_OK;	      } else		  http->state = HTTP_OK;	  }	  break;          case HTTP_KILL_PIPE:	      if (host == NULL) return HT_ERROR;	      HTHost_killPipe(host);	      return HT_OK;	      break;	  case HTTP_ERROR:	      HTTPCleanup(request, http->result);	      return HT_OK;	      break;	default:	    HTDEBUGBREAK("Bad http state %d\n" _ http->state);	}    } /* End of while(1) */}    PUBLIC void HTTP_setConnectionMode (HTTPConnectionMode mode){    ConnectionMode = mode;}PUBLIC HTTPConnectionMode HTTP_connectionMode (void){    return ConnectionMode;}PUBLIC BOOL HTTP_setBodyWriteDelay (ms_t first_try, ms_t second_try){	if (first_try > 20 && second_try >= first_try) {	    HTFirstWriteDelay = first_try;		HTSecondWriteDelay = second_try;		return YES;	}	return NO;}PUBLIC void HTTP_bodyWriteDelay (ms_t * first_try, ms_t * second_try){	*first_try = HTFirstWriteDelay;	*second_try = HTSecondWriteDelay;}

⌨️ 快捷键说明

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