Annotation of libwww/Library/src/HTNet.c, revision 2.36
2.23 frystyk 1: /* HTNet.c
2: ** ASYNCRONOUS SOCKET MANAGEMENT
2.1 frystyk 3: **
2.10 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.4 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
6: **
7: ** This is the implementation of the internal library multithreading
2.1 frystyk 8: ** functions. This includes an interrupt handler and a event loop.
9: **
10: ** History:
2.14 frystyk 11: ** 12 June 94 Written by Henrik Frystyk, frystyk@w3.org
2.17 frystyk 12: ** 31 May 95 Charlie Brooks cbrooks@osf.org
13: **
2.1 frystyk 14: */
15:
2.9 frystyk 16: /* Implemention dependent include files */
17: #include "tcp.h"
18:
2.1 frystyk 19: /* Library include files */
20: #include "HTUtils.h"
2.16 frystyk 21: #include "HTProt.h"
2.1 frystyk 22: #include "HTError.h"
2.25 frystyk 23: #include "HTAlert.h"
2.23 frystyk 24: #include "HTReqMan.h"
2.17 frystyk 25: #include "HTEvntrg.h"
2.23 frystyk 26: #include "HTStream.h"
2.24 frystyk 27: #include "HTNetMan.h" /* Implemented here */
2.1 frystyk 28:
2.9 frystyk 29: #ifdef WIN32
30: #include <io.h>
31: #endif
32:
2.23 frystyk 33: #ifndef HT_MAX_SOCKETS
34: #define HT_MAX_SOCKETS 6
35: #endif
36:
2.33 frystyk 37: typedef struct _NetCall {
2.30 frystyk 38: HTNetCallback * cbf;
2.23 frystyk 39: int status; /* Status associated with this callback */
2.33 frystyk 40: } NetCall;
2.23 frystyk 41:
42: struct _HTStream {
43: CONST HTStreamClass * isa;
44: /* ... */
45: };
46:
47: PRIVATE int HTMaxActive = HT_MAX_SOCKETS; /* Max active requests */
2.33 frystyk 48: PRIVATE HTList *HTBefore = NULL; /* List of call back functions */
49: PRIVATE HTList *HTAfter = NULL; /* List of call back functions */
2.24 frystyk 50:
2.23 frystyk 51: PRIVATE HTList *HTNetActive = NULL; /* List of active requests */
52: PRIVATE HTList *HTNetPending = NULL; /* List of pending requests */
2.24 frystyk 53: PRIVATE HTList *HTNetPersistent = NULL; /* List of persistent connections */
2.1 frystyk 54:
55: /* ------------------------------------------------------------------------- */
56:
2.23 frystyk 57: /*
58: ** Set the max number of simultanous sockets. Default is HT_MAX_SOCKETS
2.1 frystyk 59: */
2.23 frystyk 60: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
61: {
62: if (newmax > 0) {
63: HTMaxActive = newmax;
64: return YES;
65: }
66: return NO;
67: }
68:
69: PUBLIC int HTNet_maxSocket (void)
2.1 frystyk 70: {
2.23 frystyk 71: return HTMaxActive;
72: }
73:
74: /* ------------------------------------------------------------------------- */
2.33 frystyk 75: /* Call Back Functions */
2.23 frystyk 76: /* ------------------------------------------------------------------------- */
77:
2.33 frystyk 78: /* HTNetCall_add
79: ** -------------
80: ** Register a call back function that is to be called on every request.
81: ** Several call back functions can be registered
2.23 frystyk 82: ** in which case all of them are called in the order of which they
83: ** were registered.
84: **
85: ** The status signifies which call back function to call depending of the
86: ** result of the request. This can be
87: **
88: ** HT_ERROR An error occured
89: ** HT_LOADED The document was loaded
90: ** HT_NO_DATA OK, but no data
2.33 frystyk 91: ** HT_REDIRECT If we received a redirection
2.23 frystyk 92: ** HT_RETRY Retry request after at a later time
93: ** HT_ALL All of above
94: */
2.33 frystyk 95: PUBLIC BOOL HTNetCall_add (HTList * list, HTNetCallback *cbf, int status)
2.23 frystyk 96: {
2.33 frystyk 97: if (WWWTRACE)
98: TTYPrint(TDEST, "Call Add.... HTNetCallback %p\n", (void *) cbf);
99: if (list && cbf) {
100: NetCall *me = (NetCall *) calloc(1, sizeof(NetCall));
101: if (!me) outofmem(__FILE__, "HTNet_register");
102: me->cbf = cbf;
103: me->status = status;
104: return HTList_addObject(list, (void *) me);
2.23 frystyk 105: }
106: return NO;
107: }
108:
2.33 frystyk 109: /* HTNetCall_delete
110: ** ----------------
111: ** Unregister a call back function from a list
2.23 frystyk 112: */
2.33 frystyk 113: PUBLIC BOOL HTNetCall_delete (HTList * list, HTNetCallback *cbf)
2.23 frystyk 114: {
2.33 frystyk 115: if (WWWTRACE)
116: TTYPrint(TDEST, "Call delete HTNetCallback %p\n", (void *) cbf);
117: if (list && cbf) {
118: HTList *cur = list;
119: NetCall *pres;
120: while ((pres = (NetCall *) HTList_nextObject(cur))) {
2.23 frystyk 121: if (pres->cbf == cbf) {
2.33 frystyk 122: HTList_removeObject(list, (void *) pres);
2.23 frystyk 123: free(pres);
124: return YES;
125: }
126: }
127: }
128: return NO;
129: }
2.1 frystyk 130:
2.33 frystyk 131: /* HTNetCall_deleteAll
2.23 frystyk 132: ** -------------------
133: ** Unregisters all call back functions
134: */
2.33 frystyk 135: PUBLIC BOOL HTNetCall_deleteAll (HTList * list)
2.23 frystyk 136: {
2.33 frystyk 137: if (WWWTRACE)
138: TTYPrint(TDEST, "Call delete All callback functions\n");
139: if (list) {
140: HTList *cur = list;
141: NetCall *pres;
142: while ((pres = (NetCall *) HTList_nextObject(cur))) {
143: HTList_removeObject(list, (void *) pres);
2.23 frystyk 144: free(pres);
145: }
2.33 frystyk 146: HTList_delete(list);
2.23 frystyk 147: return YES;
148: }
149: return NO;
150: }
151:
2.33 frystyk 152: /* HTNetCall_execute
153: ** -----------------
2.23 frystyk 154: ** Call all the call back functions registered in the list IF not the
155: ** status is HT_IGNORE.
156: ** The callback functions are called in the order of which they
157: ** were registered. At the moment an application callback function is
158: ** called, it can free the request object - it is no longer used by the
159: ** Library.
2.33 frystyk 160: ** Returns what the last callback function returns
2.23 frystyk 161: */
2.33 frystyk 162: PUBLIC int HTNetCall_execute (HTList * list, HTRequest * request, int status)
2.23 frystyk 163: {
2.33 frystyk 164: int ret = HT_OK;
165: if (list && request && status != HT_IGNORE) {
166: int cnt = HTList_count(list);
2.23 frystyk 167: while (--cnt >= 0) {
2.33 frystyk 168: NetCall *pres = (NetCall *) HTList_objectAt(list, cnt);
2.23 frystyk 169: if (pres && (pres->status == status || pres->status == HT_ALL)) {
2.33 frystyk 170: if (WWWTRACE)
171: TTYPrint(TDEST,"Net callback %p (request=%p, status=%d)\n",
2.23 frystyk 172: (void *) pres->cbf, request, status);
2.33 frystyk 173: if ((ret = (*(pres->cbf))(request, status)) != HT_OK) break;
2.23 frystyk 174: }
175: }
2.1 frystyk 176: }
2.33 frystyk 177: return ret;
178: }
179:
180: /*
181: ** Global set of callback functions BEFORE the request is issued
182: ** list can be NULL
183: */
184: PUBLIC BOOL HTNet_setBefore (HTList *list)
185: {
186: if (HTBefore) HTNetCall_deleteAll(HTBefore);
187: HTBefore = list;
188: return YES;
189: }
190:
191: PUBLIC HTList * HTNet_before (void)
192: {
193: return HTBefore;
194: }
195:
196: PUBLIC int HTNet_callBefore (HTRequest *request, int status)
197: {
198: return HTNetCall_execute(HTBefore, request, status);
199: }
200:
201: PUBLIC BOOL HTNetCall_addBefore (HTNetCallback *cbf, int status)
202: {
203: if (!HTBefore) HTBefore = HTList_new();
204: return HTNetCall_add(HTBefore, cbf, status);
205: }
206:
207: /*
208: ** Global set of callback functions AFTER the request is issued
209: ** list can be NULL
210: */
211: PUBLIC BOOL HTNet_setAfter (HTList *list)
212: {
213: if (HTAfter) HTNetCall_deleteAll(HTAfter);
214: HTAfter = list;
215: return YES;
216: }
217:
218: PUBLIC HTList * HTNet_after (void)
219: {
220: return HTAfter;
221: }
222:
223: PUBLIC int HTNet_callAfter (HTRequest *request, int status)
224: {
225: return HTNetCall_execute(HTAfter, request, status);
226: }
227:
228: PUBLIC BOOL HTNetCall_addAfter (HTNetCallback *cbf, int status)
229: {
230: if (!HTAfter) HTAfter = HTList_new();
231: return HTNetCall_add(HTAfter, cbf, status);
2.1 frystyk 232: }
233:
2.23 frystyk 234: /* ------------------------------------------------------------------------- */
235: /* Request Queue */
236: /* ------------------------------------------------------------------------- */
2.1 frystyk 237:
2.23 frystyk 238: /* HTNet_activeQueue
239: ** -----------------
240: ** Returns the list of active requests that are currently having an open
241: ** connection.
242: ** Returns list of HTNet objects or NULL if error
2.1 frystyk 243: */
2.23 frystyk 244: PUBLIC HTList *HTNet_activeQueue (void)
245: {
246: return HTNetActive;
247: }
2.17 frystyk 248:
2.28 frystyk 249: /* HTNet_activeCount
250: ** ----------------
251: ** Returns the number of active requests
252: */
2.29 frystyk 253: PUBLIC BOOL HTNet_idle (void)
2.28 frystyk 254: {
2.29 frystyk 255: return HTList_isEmpty(HTNetActive);
2.28 frystyk 256: }
257:
2.23 frystyk 258: /* HTNet_pendingQueue
259: ** ------------------
260: ** Returns the list of pending requests that are waiting to become active
261: ** Returns list of HTNet objects or NULL if error
262: */
263: PUBLIC HTList *HTNet_pendingQueue (void)
2.1 frystyk 264: {
2.23 frystyk 265: return HTNetPending;
2.1 frystyk 266: }
267:
2.23 frystyk 268: /* ------------------------------------------------------------------------- */
269: /* Creation and deletion methods */
270: /* ------------------------------------------------------------------------- */
271:
2.27 frystyk 272: /* HTNet_duplicate
273: ** ---------------
274: ** Creates a new HTNet object as a duplicate of the same request.
275: ** Returns YES if OK, else NO
276: ** BUG: We do not check if we have a socket free!
277: */
278: PUBLIC BOOL HTNet_dup (HTNet *src, HTNet **dest)
279: {
280: *dest = NULL;
281: if (!src) return NO;
282: if ((*dest = (HTNet *) calloc(1, sizeof(HTNet))) == NULL)
283: outofmem(__FILE__, "HTNet_dup");
284: memcpy(*dest, src, sizeof(HTNet));
285: return YES;
286: }
287:
2.30 frystyk 288: /* HTNet_priority
289: ** --------------
290: ** Get the current priority of the Net object
291: */
292: PUBLIC HTPriority HTNet_priority (HTNet * net)
293: {
294: return (net ? net->priority : -1);
295: }
296:
297: /* HTNet_setPriority
298: ** -----------------
299: ** Set the current priority of the Net object
300: ** This will change the priority next time the thread is blocked
301: */
302: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
303: {
304: if (net) {
305: net->priority = priority;
306: return YES;
307: }
308: return NO;
309: }
310:
2.36 ! frystyk 311: /* create_object
! 312: ** -------------
! 313: ** Creates an HTNet object
! 314: */
! 315: PRIVATE HTNet * create_object (HTRequest * request)
! 316: {
! 317: HTNet * me;
! 318: if ((me = (HTNet *) calloc(1, sizeof(HTNet))) == NULL)
! 319: outofmem(__FILE__, "HTNet_new");
! 320: me->request = request;
! 321: request->net = me;
! 322: return me;
! 323: }
! 324:
! 325:
2.30 frystyk 326: /* HTNet_new
327: ** ---------
2.23 frystyk 328: ** Create a new HTNet object as a new request to be handled. If we have
329: ** more than HTMaxActive connections already then put this into the
330: ** pending queue, else start the request by calling the call back
331: ** function registered with this access method.
332: ** Returns YES if OK, else NO
333: */
2.30 frystyk 334: PUBLIC BOOL HTNet_new (HTRequest * request)
2.23 frystyk 335: {
2.33 frystyk 336: int status;
337: HTNet * me;
2.23 frystyk 338: HTProtocol *prot;
2.33 frystyk 339: char * physical;
2.27 frystyk 340: if (!request) return NO;
2.33 frystyk 341: /*
342: ** First we do all the "BEFORE" callbacks in order to see if we are to
343: ** continue with this request or not. If we receive a callback status
344: ** that is NOT HT_OK then jump directly to the after callbacks and return
345: */
2.34 frystyk 346: if ((status = HTNetCall_execute(HTBefore, request, HT_OK)) != HT_OK) {
2.33 frystyk 347: HTNetCall_execute(HTAfter, request, status);
348: return YES;
349: }
350:
2.36 ! frystyk 351: /*
! 352: ** If no translation was provided by the application then use the anchor
! 353: ** address directly
! 354: */
2.33 frystyk 355: if (!(physical = HTAnchor_physical(request->anchor)) || !*physical) {
2.36 ! frystyk 356: char * addr = HTAnchor_address((HTAnchor *) request->anchor);
! 357: if (WWWTRACE) TTYPrint(TDEST, "HTNet New... USING DEFAULT ADDRESS!\n");
! 358: HTAnchor_setPhysical(request->anchor, addr);
! 359: HTProtocol_find(request, request->anchor);
! 360: FREE(addr);
2.33 frystyk 361: }
362:
2.23 frystyk 363: if (!HTNetActive) HTNetActive = HTList_new();
2.26 frystyk 364: prot = (HTProtocol *) HTAnchor_protocol(request->anchor);
2.23 frystyk 365:
366: /* Create new net object and bind it to the request object */
2.36 ! frystyk 367: if ((me = create_object(request)) == NULL) return NO;
2.23 frystyk 368: me->preemtive = (HTProtocol_preemtive(prot) || request->preemtive);
2.30 frystyk 369: me->priority = request->priority;
2.23 frystyk 370: me->sockfd = INVSOC;
371: if (!(me->cbf = HTProtocol_callback(prot))) {
2.36 ! frystyk 372: if (WWWTRACE) TTYPrint(TDEST, "HTNet_new... NO CALL BACK FUNCTION!\n");
2.23 frystyk 373: free(me);
374: return NO;
375: }
2.25 frystyk 376: request->retrys++;
2.23 frystyk 377:
378: /*
379: ** Check if we can start the request, else put it into pending queue
380: ** If so then call the call back function associated with the anchor.
381: ** We use the INVSOC as we don't have a valid socket yet!
382: */
383: if (HTList_count(HTNetActive) < HTMaxActive) {
384: HTList_addObject(HTNetActive, (void *) me);
2.33 frystyk 385: if (WWWTRACE)
2.31 frystyk 386: TTYPrint(TDEST, "HTNet_new... starting request %p (retry=%d)\n",
2.25 frystyk 387: request, request->retrys);
388: (*(me->cbf))(me->sockfd, request, FD_NONE);
2.23 frystyk 389: } else {
2.35 frystyk 390: HTAlertCallback *cbf = HTAlert_find(HT_PROG_WAIT);
2.23 frystyk 391: if (!HTNetPending) HTNetPending = HTList_new();
2.33 frystyk 392: if (WWWTRACE)
2.31 frystyk 393: TTYPrint(TDEST, "HTNet_new... request %p registered as pending\n",
2.25 frystyk 394: request);
2.35 frystyk 395: if (cbf) (*cbf)(request, HT_PROG_WAIT, HT_MSG_NULL, NULL, NULL, NULL);
2.25 frystyk 396: HTList_addObject(HTNetPending, (void *) me);
2.23 frystyk 397: }
398: return YES;
399: }
400:
2.36 ! frystyk 401: /* HTNet_create
! 402: ** ------------
! 403: ** This function creates a new HTNet object and assigns the socket number
! 404: ** to it. This is intended to be used when you are going to listen on a
! 405: ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
! 406: ** call any of the callback functions.
! 407: ** Returns YES if OK, else NO
! 408: */
! 409: PUBLIC BOOL HTNet_create (HTRequest * request, SOCKET sockfd)
! 410: {
! 411: HTNet * me;
! 412: if (WWWTRACE) TTYPrint(TDEST, "HTNet_create empty Net object\n");
! 413: if (!request || sockfd==INVSOC) return NO;
! 414: if ((me = create_object(request)) == NULL) return NO;
! 415: me->preemtive = request->preemtive;
! 416: me->priority = request->priority;
! 417: me->sockfd = sockfd;
! 418: return YES;
! 419: }
! 420:
2.23 frystyk 421: /* delete_object
422: ** -------------
423: ** Deletes an HTNet object
2.15 frystyk 424: */
2.23 frystyk 425: PRIVATE BOOL delete_object (HTNet *net, int status)
2.15 frystyk 426: {
2.33 frystyk 427: if (WWWTRACE)
2.31 frystyk 428: TTYPrint(TDEST, "HTNet_delete Remove net object %p\n", net);
2.23 frystyk 429: if (net) {
430: int status = 0;
431:
432: /* Free stream with data FROM network to application */
433: if (net->target) {
434: if (status == HT_INTERRUPTED)
435: (*net->target->isa->abort)(net->target, NULL);
436: else
437: (*net->target->isa->_free)(net->target);
438: }
439:
440: /* Close socket */
441: if (net->sockfd != INVSOC) {
2.24 frystyk 442: if (HTDNS_socket(net->dns) == INVSOC) {
443: if ((status = NETCLOSE(net->sockfd)) < 0)
2.33 frystyk 444: HTRequest_addSystemError(net->request, ERR_FATAL,
445: socerrno, NO, "NETCLOSE");
446: if (WWWTRACE)
2.31 frystyk 447: TTYPrint(TDEST, "HTNet_delete closing %d\n", net->sockfd);
2.25 frystyk 448: HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
2.24 frystyk 449: } else {
2.33 frystyk 450: if (WWWTRACE)
2.31 frystyk 451: TTYPrint(TDEST, "HTNet_delete keeping %d\n", net->sockfd);
2.25 frystyk 452: HTDNS_clearActive(net->dns);
453: /* Here we should probably use a low priority */
2.27 frystyk 454: HTEvent_UnRegister(net->sockfd, (SockOps) FD_ALL);
2.25 frystyk 455: HTEvent_Register(net->sockfd, net->request, (SockOps) FD_READ,
456: HTDNS_closeSocket, net->priority);
2.24 frystyk 457: }
2.23 frystyk 458: }
459: if (net->isoc)
460: HTInputSocket_free(net->isoc);
461: if (net->request)
462: net->request->net = NULL; /* Break link to request */
463: free(net);
464: return status ? NO : YES;
465: }
466: return NO;
467: }
468:
469: /* HTNet_delete
470: ** ------------
471: ** Deletes the HTNet object from the list of active requests and calls
472: ** any registered call back functions IF not the status is HT_IGNORE.
473: ** This is used if we have internal requests that the app doesn't know
474: ** about. We also see if we have pending requests that can be started
475: ** up now when we have a socket free.
476: ** The callback functions are called in the reverse order of which they
477: ** were registered (last one first)
478: */
479: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
480: {
2.33 frystyk 481: if (WWWTRACE)
482: TTYPrint(TDEST,"HTNetDelete. Object and call callback functions\n");
2.23 frystyk 483: if (HTNetActive && net) {
2.36 ! frystyk 484: SOCKET cs = net->sockfd; /* Current sockfd */
2.23 frystyk 485:
486: /* Remove object and call callback functions */
487: HTRequest *request = net->request;
488: HTList_removeObject(HTNetActive, (void *) net);
489: delete_object(net, status);
2.33 frystyk 490: HTNetCall_execute(HTAfter, request, status);
2.23 frystyk 491:
2.25 frystyk 492: /*
493: ** See first if we have a persistent request queued up for this socket
494: ** If not then see if there is a pending request
495: */
496: if (HTNetPersistent) {
497: HTList *cur = HTNetPersistent;
498: HTNet *next;
499: while ((next = (HTNet *) HTList_nextObject(cur))) {
500: if (next->sockfd == cs) {
2.33 frystyk 501: if (WWWTRACE)
2.31 frystyk 502: TTYPrint(TDEST, "HTNet delete launch WARM request %p\n",
2.25 frystyk 503: next->request);
2.28 frystyk 504: HTList_addObject(HTNetActive, (void *) next);
505: HTList_removeObject(HTNetPersistent, (void *) next);
2.25 frystyk 506: (*(next->cbf))(next->sockfd, next->request, FD_NONE);
507: break;
508: }
509: }
510: } else if (HTList_count(HTNetActive) < HTMaxActive &&
511: HTList_count(HTNetPending)) {
2.23 frystyk 512: HTNet *next = (HTNet *) HTList_removeFirstObject(HTNetPending);
513: if (next) {
514: HTList_addObject(HTNetActive, (void *) next);
2.33 frystyk 515: if (WWWTRACE)
2.31 frystyk 516: TTYPrint(TDEST,"HTNet delete launch PENDING request %p\n",
2.23 frystyk 517: next->request);
518: (*(next->cbf))(INVSOC, next->request, FD_NONE);
519: }
520: }
521: return YES;
522: }
523: return NO;
524: }
525:
526: /* HTNet_deleteAll
527: ** ---------------
528: ** Deletes all HTNet object that might either be active or pending
2.25 frystyk 529: ** We DO NOT call the call back functions - A crude way of saying goodbye!
2.23 frystyk 530: */
531: PUBLIC BOOL HTNet_deleteAll (void)
532: {
2.33 frystyk 533: if (WWWTRACE)
2.31 frystyk 534: TTYPrint(TDEST, "HTNetDelete. Remove all Net objects, NO callback\n");
2.25 frystyk 535: if (HTNetPersistent) {
536: HTList *cur = HTNetPersistent;
537: HTNet *pres;
538: while ((pres = (HTNet *) HTList_nextObject(cur))) {
539: pres->sockfd = INVSOC; /* Don't close it more than once */
540: delete_object(pres, HT_INTERRUPTED);
541: }
542: HTList_delete(HTNetPersistent);
543: HTNetPersistent = NULL;
544: }
2.23 frystyk 545: if (HTNetPending) {
546: HTList *cur = HTNetPending;
547: HTNet *pres;
548: while ((pres = (HTNet *) HTList_nextObject(cur)))
549: delete_object(pres, HT_INTERRUPTED);
550: HTList_delete(HTNetPending);
551: HTNetPending = NULL;
552: }
553: if (HTNetActive) {
554: HTList *cur = HTNetActive;
555: HTNet *pres;
556: while ((pres = (HTNet *) HTList_nextObject(cur)))
557: delete_object(pres, HT_INTERRUPTED);
558: HTList_delete(HTNetActive);
559: HTNetActive = NULL;
560: }
561: return NO;
2.15 frystyk 562: }
563:
2.25 frystyk 564: /* HTNet_wait
565: ** ----------
566: ** Let a net object wait for a persistent socket. It will be launched
567: ** from the HTNet_delete() function
568: */
569: PUBLIC BOOL HTNet_wait (HTNet *net)
570: {
571: if (net) {
2.33 frystyk 572: if (WWWTRACE)
2.31 frystyk 573: TTYPrint(TDEST,"HTNet_wait.. request %p is waiting for socket %d\n",
2.25 frystyk 574: net->request, net->sockfd);
575: if (!HTNetPersistent) HTNetPersistent = HTList_new();
576: HTList_addObject(HTNetPersistent, (void *) net);
577: return YES;
578: }
579: return NO;
580: }
581:
2.23 frystyk 582: /* ------------------------------------------------------------------------- */
583: /* Killing requests */
584: /* ------------------------------------------------------------------------- */
585:
586: /* HTNet_kill
587: ** ----------
588: ** Kill the request by calling the call back function with a request for
589: ** closing the connection. Does not remove the object. This is done by
590: ** HTNet_delete() function which is called by the load routine.
591: ** Returns OK if success, NO on error
592: */
593: PUBLIC BOOL HTNet_kill (HTNet * me)
594: {
595: if (HTNetActive && me) {
2.25 frystyk 596: HTList *cur = HTNetActive;
2.23 frystyk 597: HTNet *pres;
2.25 frystyk 598: while ((pres = (HTNet *) HTList_nextObject(cur))) {
2.23 frystyk 599: if (pres == me) {
2.25 frystyk 600: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 601: return YES;
602: }
603: }
604: }
2.33 frystyk 605: if (WWWTRACE)
2.31 frystyk 606: TTYPrint(TDEST, "HTNet_kill.. object %p is not registered\n", me);
2.23 frystyk 607: return NO;
608: }
609:
610: /* HTNet_killAll
611: ** -------------
612: ** Kills all registered (active+pending) requests by calling the call
613: ** back function with a request for closing the connection. We do not
614: ** remove the HTNet object as it is done by HTNet_delete().
615: ** Returns OK if success, NO on error
616: */
617: PUBLIC BOOL HTNet_killAll (void)
618: {
619: HTNet *pres;
2.33 frystyk 620: if (WWWTRACE)
2.31 frystyk 621: TTYPrint(TDEST, "HTNet_kill.. ALL registered requests!!!\n");
2.23 frystyk 622:
2.25 frystyk 623: /* We start off in persistent queue so we avoid racing */
624: if (HTNetPersistent) {
625: while ((pres = (HTNet *) HTList_lastObject(HTNetPersistent)) != NULL) {
626: pres->sockfd = INVSOC;
627: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
628: HTList_removeObject(HTNetPersistent, pres);
629: }
630: }
2.23 frystyk 631: if (HTNetPending) {
632: while ((pres = (HTNet *) HTList_lastObject(HTNetPending)) != NULL) {
2.25 frystyk 633: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 634: HTList_removeObject(HTNetPending, pres);
635: }
636: }
637: if (HTNetActive) {
638: while ((pres = (HTNet *) HTList_lastObject(HTNetActive)) != NULL)
2.25 frystyk 639: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 640: }
641: return YES;
642: }
Webmaster