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