📄 hthost.c
字号:
PUBLIC int HTHost_listen (HTHost * host, HTNet * net, char * url){ HTRequest * request = HTNet_request(net); int status = HT_OK; if (!host) { HTProtocol * protocol = HTNet_protocol(net); if ((host = HTHost_newWParse(request, url, HTProtocol_id(protocol))) == NULL) return HT_ERROR; /* ** If not already locked and without a channel ** then lock the darn thing with the first Net object ** pending. */ if (!host->lock && !host->channel) { host->forceWriteFlush = YES; host->lock = net; } HTNet_setHost(net, host); } /* ** See if we already have a dedicated listen Net object. If not ** then create one. */ if (!host->listening) host->listening = HTNet_new(host); /* ** Start listening on the Net object */ status = HTDoListen(host->listening, net, HT_BACKLOG); if (status != HT_OK) { HTTRACE(CORE_TRACE, "Host listen. On Host %p resulted in %d\n" _ host _ status); return status; } return HT_OK;}PUBLIC int HTHost_accept (HTHost * host, HTNet * net, char * url){ int status = HT_OK; if (!host || !host->listening) { HTTRACE(CORE_TRACE, "Host accept. No host object or not listening on anything\n"); return HT_ERROR; } if (!host->lock || (host->lock && host->lock == net)) { status = HTDoAccept(host->listening, net); if (status == HT_PENDING) return HT_WOULD_BLOCK; else if (status == HT_WOULD_BLOCK) { host->lock = net; return status; } else { /* ** See if there is already a new pending request that should ** take over the current lock */ HTNet * next_pending = NULL; if ((next_pending = HTList_firstObject(host->pending))) { HTTRACE(CORE_TRACE, "Host connect Changing lock on Host %p to %p\n" _ host _ next_pending); host->lock = next_pending; } else { HTTRACE(CORE_TRACE, "Host connect Unlocking Host %p\n" _ host); host->lock = NULL; } return status; } } else { HTTRACE(CORE_TRACE, "Host connect Host %p already locked with %p\n" _ host _ host->lock); if ((status = HTHost_addNet(host, net)) == HT_PENDING) { return HT_PENDING; } } return HT_ERROR;}/*** Rules: SINGLE: one element in pipe, either reading or writing** PIPE: n element in pipe, n-1 reading, 1 writing*/PUBLIC int HTHost_register (HTHost * host, HTNet * net, HTEventType type){ HTEvent *event; if (host && net) { if (type == HTEvent_CLOSE) { /* ** Unregister this host for all events */ HTEvent_unregister(HTChannel_socket(host->channel), HTEvent_READ); HTEvent_unregister(HTChannel_socket(host->channel), HTEvent_WRITE); host->registeredFor = 0; return YES; } else { /* net object may already be registered */ if (HTEvent_BITS(type) & net->registeredFor) return NO; net->registeredFor ^= HTEvent_BITS(type); /* host object may already be registered */ if (host->registeredFor & HTEvent_BITS(type)) return YES; host->registeredFor ^= HTEvent_BITS(type);#ifdef WWW_WIN_ASYNC /* Make sure we are registered for CLOSE on windows */ event = *(host->events+HTEvent_INDEX(HTEvent_CLOSE)); HTEvent_register(HTChannel_socket(host->channel), HTEvent_CLOSE, event);#endif /* WWW_WIN_ASYNC */ /* JK: register a request in the event structure */ event = *(host->events+HTEvent_INDEX(type)); event->request = HTNet_request (net); return HTEvent_register(HTChannel_socket(host->channel), type, event); } return YES; } HTTRACE(CORE_TRACE, "HTHost...... Don't register event with bad arguments\n"); return NO;}PUBLIC int HTHost_unregister (HTHost * host, HTNet * net, HTEventType type){ if (host && net) { /* net object may not be registered */ if (!(HTEvent_BITS(type) & net->registeredFor)) return NO; net->registeredFor ^= HTEvent_BITS(type); /* host object may not be registered */ if (!(host->registeredFor & HTEvent_BITS(type))) return YES; host->registeredFor ^= HTEvent_BITS(type); /* stay registered for READ to catch a socket close */ /* WRITE and CONNECT can be unregistered, though */ if ((type == HTEvent_WRITE && isLastInPipe(host, net)) || type == HTEvent_CONNECT) /* if we are blocked downstream, shut down the whole pipe */ HTEvent_unregister(HTChannel_socket(host->channel), type); return YES; } return NO;}/*** The reader tells HostEvent that it's stream did not finish the data*/PUBLIC BOOL HTHost_setRemainingRead (HTHost * host, size_t remaining){ if (host == NULL) return NO; host->remainingRead = remaining; HTTRACE(PROT_TRACE, "Host........ %d bytes remaining \n" _ remaining); if (host->broken_pipe && remaining == 0) { HTTRACE(PROT_TRACE, "Host........ Emtied out connection\n"); } return YES;}PUBLIC size_t HTHost_remainingRead (HTHost * host){ return host ? host->remainingRead : -1;}PUBLIC SockA * HTHost_getSockAddr (HTHost * host){ if (!host) return NULL; return &host->sock_addr;}PUBLIC BOOL HTHost_setHome (HTHost * host, int home){ if (!host) return NO; host->home = home; return YES;}PUBLIC int HTHost_home (HTHost * host){ if (!host) return 0; return host->home;}PUBLIC BOOL HTHost_setRetry (HTHost * host, int retry){ if (!host) return NO; host->retry = retry; return YES;}PUBLIC BOOL HTHost_decreaseRetry (HTHost * host){ if (!host) return NO; if (host->retry > 0) host->retry--; return YES;}PUBLIC int HTHost_retry (HTHost * host){ if (!host) return 0; return host->retry;}#if 0 /* Is a macro right now */PRIVATE BOOL HTHost_setDNS5 (HTHost * host, HTdns * dns){ if (!host) return NO; host->dns = dns; return YES;}#endifPUBLIC BOOL HTHost_setChannel (HTHost * host, HTChannel * channel){ if (!host) return NO; host->channel = channel; return YES;}PUBLIC HTNet * HTHost_getReadNet(HTHost * host){ return host ? (HTNet *) HTList_firstObject(host->pipeline) : NULL;}PUBLIC HTNet * HTHost_getWriteNet(HTHost * host){ return host ? (HTNet *) HTList_lastObject(host->pipeline) : NULL;}/*** Create the input stream and bind it to the channel** Please read the description in the HTIOStream module for the parameters*/PUBLIC HTInputStream * HTHost_getInput (HTHost * host, HTTransport * tp, void * param, int mode){ if (host && host->channel && tp) { HTChannel * ch = host->channel; HTInputStream * input = (*tp->input_new)(host, ch, param, mode); HTChannel_setInput(ch, input); return HTChannel_getChannelIStream(ch); } HTTRACE(CORE_TRACE, "Host Object. Can't create input stream\n"); return NULL;}PUBLIC HTOutputStream * HTHost_getOutput (HTHost * host, HTTransport * tp, void * param, int mode){ if (host && host->channel && tp) { HTChannel * ch = host->channel; HTOutputStream * output = (*tp->output_new)(host, ch, param, mode); HTChannel_setOutput(ch, output); return output; } HTTRACE(CORE_TRACE, "Host Object. Can't create output stream\n"); return NULL;}PUBLIC HTOutputStream * HTHost_output (HTHost * host, HTNet * net){ if (host && host->channel && net) { HTOutputStream * output = HTChannel_output(host->channel); return output; } return NULL;}PUBLIC int HTHost_read(HTHost * host, HTNet * net){ HTInputStream * input = HTChannel_input(host->channel); if (net != HTHost_getReadNet(host)) { HTHost_register(host, net, HTEvent_READ); return HT_WOULD_BLOCK; } /* ** If there is no input channel then this can either mean that ** we have lost the channel or an error occurred. We return ** HT_CLOSED as this is a sign to the caller that we don't ** have a channel */ return input ? (*input->isa->read)(input) : HT_CLOSED;}PUBLIC BOOL HTHost_setConsumed(HTHost * host, size_t bytes){ HTInputStream * input; if (!host || !host->channel) return NO; if ((input = HTChannel_input(host->channel)) == NULL) return NO; HTTRACE(CORE_TRACE, "Host........ passing %d bytes as consumed to %p\n" _ bytes _ input); return (*input->isa->consumed)(input, bytes);}PUBLIC int HTHost_hash (HTHost * host){ return host ? host->hash : -1;}PUBLIC BOOL HTHost_setWriteDelay (HTHost * host, ms_t delay){ if (host && delay >= 0) { host->delay = delay; return YES; } return NO;}PUBLIC ms_t HTHost_writeDelay (HTHost * host){ return host ? host->delay : 0;}PUBLIC int HTHost_findWriteDelay (HTHost * host, ms_t lastFlushTime, int buffSize){#if 0 unsigned short mtu; int ret = -1; int socket = HTChannel_socket(host->channel);#ifndef WWW_MSWINDOWS ret = ioctl(socket, 666, (unsigned long)&mtu);#endif /* WWW_MSWINDOWS */ if ((ret == 0 && buffSize >= mtu) || host->forceWriteFlush) return 0; return host->delay;#else return host->forceWriteFlush ? 0 : host->delay;#endif}PUBLIC BOOL HTHost_setDefaultWriteDelay (ms_t delay){ if (delay >= 0) { WriteDelay = delay; HTTRACE(CORE_TRACE, "Host........ Default write delay is %d ms\n" _ delay); return YES; } return NO;}PUBLIC ms_t HTHost_defaultWriteDelay (void){ return WriteDelay;}PUBLIC int HTHost_forceFlush(HTHost * host){ HTNet * targetNet = (HTNet *) HTList_lastObject(host->pipeline); int ret; if (targetNet == NULL) return HT_ERROR; /* 2000/28/07 JK: The following test was proposed by Heiner Kallweit, as there's a problem ** while using SSL because of a recursive call to this function. We tested the ** fix and it doesn't seem to introduce any side effects... but one never knows, ** thus this comment. This seems more like a bug in the SSL code than here. */ if (host->inFlush) { HTTRACE(CORE_TRACE, "Host Event.. FLUSH requested for `%s\'\n, but ignoring it as we're already processing a flush in this host" _ HTAnchor_physical(HTRequest_anchor(HTNet_request(targetNet)))); return HT_OK; } HTTRACE(CORE_TRACE, "Host Event.. FLUSH passed to `%s\'\n" _ HTAnchor_physical(HTRequest_anchor(HTNet_request(targetNet)))); host->forceWriteFlush = YES; host->inFlush = YES; ret = (*targetNet->event.cbf)(HTChannel_socket(host->channel), targetNet->event.param, HTEvent_FLUSH); host->forceWriteFlush = NO; host->inFlush = NO; return ret;}/*** Context pointer to be used as a user defined context */PUBLIC void HTHost_setContext (HTHost * me, void * context){ if (me) me->context = context;}PUBLIC void * HTHost_context (HTHost * me){ return me ? me->context : NULL;}PUBLIC int HTHost_eventTimeout (void){ return EventTimeout;}PUBLIC void HTHost_setEventTimeout (int millis){ EventTimeout = millis; HTTRACE(CORE_TRACE, "Host........ Setting event timeout to %d ms\n" _ millis);}PUBLIC BOOL HTHost_setMaxPipelinedRequests (int max){ if (max > 1) { MaxPipelinedRequests = max; return YES; } return NO;}PUBLIC int HTHost_maxPipelinedRequests (void){ return MaxPipelinedRequests;}PUBLIC void HTHost_setActivateRequestCallback (HTHost_ActivateRequestCallback * cbf){ HTTRACE(CORE_TRACE, "HTHost...... Registering %p\n" _ cbf); ActivateReqCBF = cbf;}PRIVATE int HTHost_ActivateRequest (HTNet * net){ HTRequest * request = NULL; if (!ActivateReqCBF) { HTTRACE(CORE_TRACE, "HTHost...... No ActivateRequest callback handler registered\n"); return HT_ERROR; } request = HTNet_request(net); return (*ActivateReqCBF)(request);}PUBLIC void HTHost_disable_PendingReqLaunch (void){ DoPendingReqLaunch = NO;}PUBLIC void HTHost_enable_PendingReqLaunch (void){ DoPendingReqLaunch = YES;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -