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