📄 htnet.c
字号:
if (newmax > 0) { MaxActive = newmax; return YES; } return NO;}PUBLIC void HTNet_increaseSocket (void){ Active++; HTTRACE(CORE_TRACE, "Net Manager. Increasing active sockets to %d, %d persistent sockets\n" _ Active _ Persistent);}PUBLIC void HTNet_decreaseSocket (void){ if (--Active < 0) Active = 0; HTTRACE(CORE_TRACE, "Net Manager. Decreasing active sockets to %d, %d persistent sockets\n" _ Active _ Persistent);}PUBLIC int HTNet_availableSockets (void){ int available = MaxActive - Active; return available > 0 ? available : 0;}PUBLIC void HTNet_increasePersistentSocket (void){ Persistent++; HTTRACE(CORE_TRACE, "Net Manager. %d active sockets, increasing persistent sockets to %d\n" _ Active _ Persistent);}PUBLIC void HTNet_decreasePersistentSocket (void){ if (--Persistent < 0) Persistent = 0; HTTRACE(CORE_TRACE, "Net Manager. %d active sockets, decreasing persistent sockets to %d\n" _ Active _ Persistent);}PUBLIC int HTNet_availablePersistentSockets (void){ int available = MaxActive - 2 - Persistent; return available > 0 ? available : 0;}/*** Returns whether there are any Net objects pending or active*/PUBLIC BOOL HTNet_isIdle (void){ return (HTNetCount > 0);}PUBLIC BOOL HTNet_isEmpty (void){ return (HTNetCount <= 0);}PUBLIC int HTNet_count (void){ return HTNetCount;}/* ------------------------------------------------------------------------- *//* Creation and deletion methods *//* ------------------------------------------------------------------------- */PRIVATE int AfterFilterEvent (HTTimer * timer, void * param, HTEventType type){ HTFilterEvent * fe = (HTFilterEvent *) param; if (fe) { HTRequest * request = fe->request; int status = fe->status; if (timer != fe->timer) HTDEBUGBREAK("Net timer. %p not in sync\n" _ timer); HTTRACE(CORE_TRACE, "HTNet....... Continuing calling AFTER filters %p with timer %p\n" _ fe _ timer); /* Delete the event context */ HT_FREE(fe); /* Now call the remaining AFTER filters */ return HTNet_executeAfterAll(request, status); } return HT_ERROR;}PRIVATE BOOL createAfterFilterEvent (HTRequest * request, int status){ HTFilterEvent * me = NULL; if ((me = (HTFilterEvent *) HT_CALLOC(1, sizeof(HTFilterEvent))) == NULL) HT_OUTOFMEM("createAfterFilterEvent"); me->request = request; me->status = status; me->timer = HTTimer_new(NULL, AfterFilterEvent, me, 1, YES, NO); return YES;}PRIVATE HTNet * create_object (void){ static int net_hash = 0; HTNet * me = NULL; /* Create new object */ if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL) HT_OUTOFMEM("HTNet_new"); me->hash = net_hash++ % HT_XL_HASH_SIZE; /* Insert into hash table */ if (!NetTable) { if ((NetTable = (HTList **) HT_CALLOC(HT_XL_HASH_SIZE, sizeof(HTList *))) == NULL) HT_OUTOFMEM("create_object"); } if (!NetTable[me->hash]) NetTable[me->hash] = HTList_new(); HTList_addObject(NetTable[me->hash], (void *) me); HTNetCount++; HTTRACE(CORE_TRACE, "Net Object.. %p created with hash %d\n" _ me _ me->hash); return me;}/* HTNet_duplicate** ---------------** Creates a new HTNet object as a duplicate of the same request.** Returns YES if OK, else NO** BUG: We do not check if we have a socket free!*/PUBLIC HTNet * HTNet_dup (HTNet * src){ if (src) { HTNet * me; int hash; if ((me = create_object()) == NULL) return NULL; hash = me->hash; HTTRACE(CORE_TRACE, "Net Object.. Duplicated %p\n" _ src); memcpy((void *) me, src, sizeof(HTNet)); me->hash = hash; /* Carry over hash entry */ return me; } return NULL;}PUBLIC BOOL HTNet_execute (HTNet * net, HTEventType type){ if (net && net->event.cbf && net->request) { HTTRACE(CORE_TRACE, "Net Object.. %p calling %p with event type %d and context %p\n" _ net _ net->event.cbf _ type _ net->event.param); (*(net->event.cbf))(HTNet_socket(net), net->event.param, type); return YES; } return NO;}/*** Start a Net obejct by calling the protocol module.*/PUBLIC BOOL HTNet_start (HTNet * net){ if (net && net->event.cbf && net->request) { HTTRACE(CORE_TRACE, "Net Object.. Launching %p\n" _ net); (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_BEGIN); return YES; } return NO;}/* HTNet_new** ---------** This function creates a new HTNet object and assigns the socket number** to it. This is intended to be used when you are going to listen on a ** socket using the HTDoListen() function in HTTCP.c. The function do NOT** call any of the callback functions.** Returns new object or NULL on error*/PUBLIC HTNet * HTNet_new (HTRequest * request){ HTNet * me; if ((me = create_object()) == NULL) return NULL; me->preemptive = HTRequest_preemptive(request); HTNet_setEventPriority(me, HTRequest_priority(request)); me->request = request; HTRequest_setNet(request, me); return me;}/* HTNet_newServer** ---------------** Create a new HTNet object as a new request to be handled. If we have** more than MaxActive connections already then return NO.** Returns YES if OK, else NO*/PUBLIC BOOL HTNet_newServer (HTRequest * request){ HTParentAnchor * anchor = HTRequest_anchor(request); HTNet * me = NULL; HTProtocol * protocol; HTTransport * tp = NULL; /* added JTD:5/28/96 */ char * physical = NULL; int status; HTProtCallback * cbf; if (!request) return NO; /* ** First we do all the "BEFORE" callbacks in order to see if we are to ** continue with this request or not. If we receive a callback status ** that is NOT HT_OK then jump directly to the after callbacks and return */ if ((status = HTNet_executeBeforeAll(request)) != HT_OK) { /* ** If in non-blocking mode then return here and call AFTER ** filters from a timer event handler. As Olga Antropova ** points out, otherwise, the stack can grow if new requests ** are started directly from the after filters */ if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request)) createAfterFilterEvent(request, status); else HTNet_executeAfterAll(request, status); return YES; } /* ** If no translation was provided by the filters then use the anchor ** address directly */ if (!(physical = HTAnchor_physical(anchor))) { char * addr = HTAnchor_address((HTAnchor *) anchor); HTTRACE(CORE_TRACE, "Net Object.. Using default address\n"); HTAnchor_setPhysical(anchor, addr); physical = HTAnchor_physical(anchor); HT_FREE(addr); } /* Find a protocol object for this access scheme */ { char * access = HTParse(physical, "", PARSE_ACCESS); if ((protocol = HTProtocol_find(request, access)) == NULL) { HTTRACE(CORE_TRACE, "Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n" _ access); HT_FREE(access); return NO; } if (!(cbf = HTProtocol_server(protocol))) { HTTRACE(CORE_TRACE, "Net Object.. NO SERVER HANDLER for URI scheme `%s\'\n" _ access); HT_FREE(access); HT_FREE(me); return NO; } HT_FREE(access); } /* Find a transport object for this protocol */ if ((tp = HTTransport_find(request, HTProtocol_transport(protocol))) == NULL) { HTTRACE(CORE_TRACE, "Net Object.. NO TRANSPORT found for protocol `%s\'\n" _ HTProtocol_name(protocol)); return NO; } /* Create new net object and bind to request object */ if ((me = create_object()) == NULL) return NO; me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request)); HTNet_setEventPriority(me, HTRequest_priority(request)); me->protocol = protocol; me->transport = tp; /* added - JTD:5/28/96 */ me->request = request; HTRequest_setNet(request, me); /* Start the server request */ HTTRACE(CORE_TRACE, "Net Object.. starting SERVER request %p and net object %p\n" _ request _ me); (*(cbf))(INVSOC, request); return YES;}/* HTNet_new** ---------** Create a new HTNet object as a new request to be handled. If we have** more than MaxActive connections already then put this into the** pending queue, else start the request by calling the call back** function registered with this access method. ** Returns YES if OK, else NO*/PUBLIC BOOL HTNet_newClient (HTRequest * request){ HTParentAnchor * anchor = HTRequest_anchor(request); HTNet * me = NULL; HTProtocol * protocol = NULL; HTTransport * tp = NULL; char * physical = NULL; int status; HTProtCallback * cbf; if (!request) return NO; /* ** First we do all the "BEFORE" callbacks in order to see if we are to ** continue with this request or not. If we receive a callback status ** that is NOT HT_OK then jump directly to the after callbacks and return */ if ((status = HTNet_executeBeforeAll(request)) != HT_OK) { /* ** If in non-blocking mode then return here and call AFTER ** filters from a timer event handler. As Olga Antropova ** points out, otherwise, the stack can grow if new requests ** are started directly from the after filters */ if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request)) createAfterFilterEvent(request, status); else HTNet_executeAfterAll(request, status); return YES; } /* ** If no translation was provided by the filters then use the anchor ** address directly */ if (!(physical = HTAnchor_physical(anchor))) { char * addr = HTAnchor_address((HTAnchor *) anchor); HTTRACE(CORE_TRACE, "Net Object.. Using default address\n"); HTAnchor_setPhysical(anchor, addr); physical = HTAnchor_physical(anchor); HT_FREE(addr); } /* Find a protocol object for this access scheme */ { char * proxy = HTRequest_proxy(request); char * access = HTParse(proxy ? proxy : physical, "", PARSE_ACCESS); if ((protocol = HTProtocol_find(request, access)) == NULL) { HTTRACE(CORE_TRACE, "Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n" _ access); HT_FREE(access); return NO; } if (!(cbf = HTProtocol_client(protocol))) { HTTRACE(CORE_TRACE, "Net Object.. NO CLIENT HANDLER for URI scheme `%s\'\n" _ access); HT_FREE(access); HT_FREE(me); return NO; } HT_FREE(access); } /* Find a transport object for this protocol */ tp = HTTransport_find(request, HTProtocol_transport(protocol)); if (tp == NULL) { HTTRACE(CORE_TRACE, "Net Object.. NO TRANSPORT found for protocol `%s\'\n" _ HTProtocol_name(protocol)); return NO; } /* Create new net object and bind it to the request object */ if ((me = create_object()) == NULL) return NO; me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));#if 0 me->priority = HTRequest_priority(request);#endif HTNet_setEventPriority(me, HTRequest_priority(request)); me->protocol = protocol; me->transport = tp; me->request = request; HTRequest_setNet(request, me); /* Increase the number of retrys for this download */ HTRequest_addRetry(request); /* ** Check if we can start the request, else put it into pending queue ** If so then call the call back function associated with the anchor. ** We use the INVSOC as we don't have a valid socket yet! */ HTTRACE(CORE_TRACE, "Net Object.. starting request %p (retry=%d) with net object %p\n" _ request _ HTRequest_retrys(request) _ me); (*(cbf))(INVSOC, request); return YES;}/*** Check whether we have any pending HTNet objects and if so** then start the next one.** Return YES if OK, else NO*/PRIVATE BOOL check_pending (HTNet * net){ HTTRACE(CORE_TRACE, "Net Object.. Check for pending Net objects\n"); if (net) { /* ** As we may have a socket available we check for whether ** we can start any pending requests. We do this by asking for ** pending Host objects. If none then use the current object */ HTHost_launchPending(net->host); return YES; } return NO;}PRIVATE BOOL free_net (HTNet * net){ HTTRACE(CORE_TRACE, "Net Object.. Freeing object %p\n" _ net); if (net) { HTRequest_setNet(net->request, NULL); HT_FREE(net); return YES; } return NO;}/*** Unregister the net object from the global list** and see if we can start a new pending request.*/PRIVATE BOOL unregister_net (HTNet * net){ if (net && NetTable) { HTList * list = NetTable[net->hash]; if (list) { HTList_removeObject(list, (void *) net); check_pending(net); HTNetCount--; return YES; } } return NO;}/*** Clears the contents of the Net object so that we can use it again.*/PUBLIC BOOL HTNet_clear (HTNet * net){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -