Annotation of libwww/Library/src/HTNet.c, revision 2.73
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.
2.73 ! frystyk 6: ** @(#) $Id: HTNet.c,v 2.72 1996/08/05 17:22:39 frystyk Exp $
2.4 frystyk 7: **
8: ** This is the implementation of the internal library multithreading
2.1 frystyk 9: ** functions. This includes an interrupt handler and a event loop.
10: **
11: ** History:
2.14 frystyk 12: ** 12 June 94 Written by Henrik Frystyk, frystyk@w3.org
2.17 frystyk 13: ** 31 May 95 Charlie Brooks cbrooks@osf.org
14: **
2.1 frystyk 15: */
16:
2.9 frystyk 17: /* Implemention dependent include files */
2.52 frystyk 18: #include "sysdep.h"
2.9 frystyk 19:
2.1 frystyk 20: /* Library include files */
2.59 frystyk 21: #include "WWWUtil.h"
2.16 frystyk 22: #include "HTProt.h"
2.1 frystyk 23: #include "HTError.h"
2.25 frystyk 24: #include "HTAlert.h"
2.37 frystyk 25: #include "HTParse.h"
2.59 frystyk 26: #include "HTTrans.h"
2.23 frystyk 27: #include "HTReqMan.h"
2.65 frystyk 28: #include "HTEvent.h"
2.23 frystyk 29: #include "HTStream.h"
2.24 frystyk 30: #include "HTNetMan.h" /* Implemented here */
2.1 frystyk 31:
2.23 frystyk 32: #ifndef HT_MAX_SOCKETS
33: #define HT_MAX_SOCKETS 6
34: #endif
35:
2.33 frystyk 36: typedef struct _NetCall {
2.30 frystyk 37: HTNetCallback * cbf;
2.60 frystyk 38: void * param; /* Local context */
2.23 frystyk 39: int status; /* Status associated with this callback */
2.33 frystyk 40: } NetCall;
2.23 frystyk 41:
42: struct _HTStream {
2.52 frystyk 43: const HTStreamClass * isa;
2.23 frystyk 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.60 frystyk 95: PUBLIC BOOL HTNetCall_add (HTList * list, HTNetCallback * cbf,
96: void * param, int status)
2.23 frystyk 97: {
2.58 hallam 98: if (CORE_TRACE)
2.60 frystyk 99: HTTrace("Call Add.... HTNetCallback %p with context %p\n",
100: (void *) cbf, param);
2.33 frystyk 101: if (list && cbf) {
2.49 frystyk 102: NetCall *me;
103: if ((me = (NetCall *) HT_CALLOC(1, sizeof(NetCall))) == NULL)
104: HT_OUTOFMEM("HTNetCall_add");
2.33 frystyk 105: me->cbf = cbf;
2.60 frystyk 106: me->param = param;
2.33 frystyk 107: me->status = status;
108: return HTList_addObject(list, (void *) me);
2.23 frystyk 109: }
110: return NO;
111: }
112:
2.33 frystyk 113: /* HTNetCall_delete
114: ** ----------------
115: ** Unregister a call back function from a list
2.23 frystyk 116: */
2.33 frystyk 117: PUBLIC BOOL HTNetCall_delete (HTList * list, HTNetCallback *cbf)
2.23 frystyk 118: {
2.58 hallam 119: if (CORE_TRACE)
2.50 eric 120: HTTrace("Call delete HTNetCallback %p\n", (void *) cbf);
2.33 frystyk 121: if (list && cbf) {
122: HTList *cur = list;
123: NetCall *pres;
124: while ((pres = (NetCall *) HTList_nextObject(cur))) {
2.23 frystyk 125: if (pres->cbf == cbf) {
2.33 frystyk 126: HTList_removeObject(list, (void *) pres);
2.49 frystyk 127: HT_FREE(pres);
2.23 frystyk 128: return YES;
129: }
130: }
131: }
132: return NO;
133: }
2.1 frystyk 134:
2.33 frystyk 135: /* HTNetCall_deleteAll
2.23 frystyk 136: ** -------------------
137: ** Unregisters all call back functions
138: */
2.33 frystyk 139: PUBLIC BOOL HTNetCall_deleteAll (HTList * list)
2.23 frystyk 140: {
2.58 hallam 141: if (CORE_TRACE)
2.50 eric 142: HTTrace("Call delete All callback functions\n");
2.33 frystyk 143: if (list) {
144: HTList *cur = list;
145: NetCall *pres;
146: while ((pres = (NetCall *) HTList_nextObject(cur))) {
147: HTList_removeObject(list, (void *) pres);
2.49 frystyk 148: HT_FREE(pres);
2.23 frystyk 149: }
2.33 frystyk 150: HTList_delete(list);
2.23 frystyk 151: return YES;
152: }
153: return NO;
154: }
155:
2.33 frystyk 156: /* HTNetCall_execute
157: ** -----------------
2.23 frystyk 158: ** Call all the call back functions registered in the list IF not the
159: ** status is HT_IGNORE.
160: ** The callback functions are called in the order of which they
161: ** were registered. At the moment an application callback function is
162: ** called, it can free the request object - it is no longer used by the
163: ** Library.
2.33 frystyk 164: ** Returns what the last callback function returns
2.23 frystyk 165: */
2.33 frystyk 166: PUBLIC int HTNetCall_execute (HTList * list, HTRequest * request, int status)
2.23 frystyk 167: {
2.33 frystyk 168: int ret = HT_OK;
169: if (list && request && status != HT_IGNORE) {
170: int cnt = HTList_count(list);
2.23 frystyk 171: while (--cnt >= 0) {
2.33 frystyk 172: NetCall *pres = (NetCall *) HTList_objectAt(list, cnt);
2.23 frystyk 173: if (pres && (pres->status == status || pres->status == HT_ALL)) {
2.58 hallam 174: if (CORE_TRACE)
2.50 eric 175: HTTrace("Net callback %p (request=%p, status=%d)\n",
2.23 frystyk 176: (void *) pres->cbf, request, status);
2.60 frystyk 177: if ((ret=(*(pres->cbf))(request, pres->param,status)) != HT_OK)
178: 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:
2.60 frystyk 216: PUBLIC BOOL HTNetCall_addBefore (HTNetCallback * cbf, void * param, int status)
2.33 frystyk 217: {
218: if (!HTBefore) HTBefore = HTList_new();
2.60 frystyk 219: return HTNetCall_add(HTBefore, cbf, param, status);
2.33 frystyk 220: }
221:
2.73 ! frystyk 222: PUBLIC BOOL HTNetCall_deleteBefore (HTNetCallback * cbf)
! 223: {
! 224: return HTNetCall_delete(HTBefore, cbf);
! 225: }
! 226:
2.33 frystyk 227: /*
228: ** Global set of callback functions AFTER the request is issued
229: ** list can be NULL
230: */
231: PUBLIC BOOL HTNet_setAfter (HTList *list)
232: {
2.57 eric 233: /* if (HTAfter) HTNetCall_deleteAll(HTAfter); */
2.33 frystyk 234: HTAfter = list;
235: return YES;
236: }
237:
238: PUBLIC HTList * HTNet_after (void)
239: {
240: return HTAfter;
241: }
242:
243: PUBLIC int HTNet_callAfter (HTRequest *request, int status)
244: {
2.58 hallam 245: int ret;
246: BOOL override = NO;
247: HTList * afters;
248:
249: if ((afters = HTRequest_after(request, &override))) {
250: if ((ret = HTNetCall_execute(afters, request, status)) != HT_OK)
251: return ret;
252: }
253: if (override)
254: return HT_OK;
2.33 frystyk 255: return HTNetCall_execute(HTAfter, request, status);
256: }
257:
2.60 frystyk 258: PUBLIC BOOL HTNetCall_addAfter (HTNetCallback * cbf, void * param, int status)
2.33 frystyk 259: {
260: if (!HTAfter) HTAfter = HTList_new();
2.60 frystyk 261: return HTNetCall_add(HTAfter, cbf, param, status);
2.73 ! frystyk 262: }
! 263:
! 264: PUBLIC BOOL HTNetCall_deleteAfter (HTNetCallback * cbf)
! 265: {
! 266: return HTNetCall_delete(HTBefore, cbf);
2.1 frystyk 267: }
268:
2.23 frystyk 269: /* ------------------------------------------------------------------------- */
270: /* Request Queue */
271: /* ------------------------------------------------------------------------- */
2.1 frystyk 272:
2.23 frystyk 273: /* HTNet_activeQueue
274: ** -----------------
275: ** Returns the list of active requests that are currently having an open
276: ** connection.
277: ** Returns list of HTNet objects or NULL if error
2.1 frystyk 278: */
2.23 frystyk 279: PUBLIC HTList *HTNet_activeQueue (void)
280: {
281: return HTNetActive;
282: }
2.17 frystyk 283:
2.40 frystyk 284: /* HTNet_idle
285: ** ----------
286: ** Returns whether there are active requests
2.28 frystyk 287: */
2.29 frystyk 288: PUBLIC BOOL HTNet_idle (void)
2.28 frystyk 289: {
2.29 frystyk 290: return HTList_isEmpty(HTNetActive);
2.28 frystyk 291: }
292:
2.40 frystyk 293: /* HTNet_empty
294: ** -----------
295: ** Returns whether there are requests registered or not
296: */
297: PUBLIC BOOL HTNet_isEmpty (void)
298: {
299: return (HTList_isEmpty(HTNetActive) && HTList_isEmpty(HTNetPersistent) &&
300: HTList_isEmpty(HTNetPending));
301: }
302:
2.23 frystyk 303: /* HTNet_pendingQueue
304: ** ------------------
305: ** Returns the list of pending requests that are waiting to become active
306: ** Returns list of HTNet objects or NULL if error
307: */
308: PUBLIC HTList *HTNet_pendingQueue (void)
2.1 frystyk 309: {
2.23 frystyk 310: return HTNetPending;
2.1 frystyk 311: }
312:
2.23 frystyk 313: /* ------------------------------------------------------------------------- */
314: /* Creation and deletion methods */
315: /* ------------------------------------------------------------------------- */
316:
2.27 frystyk 317: /* HTNet_duplicate
318: ** ---------------
319: ** Creates a new HTNet object as a duplicate of the same request.
320: ** Returns YES if OK, else NO
321: ** BUG: We do not check if we have a socket free!
322: */
2.43 frystyk 323: PUBLIC HTNet * HTNet_dup (HTNet * src)
2.27 frystyk 324: {
2.43 frystyk 325: HTNet * me;
2.54 eric 326: if (!src) return 0;
2.49 frystyk 327: if ((me = (HTNet *) HT_MALLOC(sizeof(HTNet))) == NULL)
328: HT_OUTOFMEM("HTNet_dup");
2.44 frystyk 329: memcpy((void *) me, src, sizeof(HTNet));
2.43 frystyk 330: return me;
2.27 frystyk 331: }
332:
2.30 frystyk 333: /* HTNet_priority
334: ** --------------
335: ** Get the current priority of the Net object
336: */
337: PUBLIC HTPriority HTNet_priority (HTNet * net)
338: {
2.51 frystyk 339: return (net ? net->priority : HT_PRIORITY_INV);
2.30 frystyk 340: }
341:
342: /* HTNet_setPriority
343: ** -----------------
344: ** Set the current priority of the Net object
345: ** This will change the priority next time the thread is blocked
346: */
347: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
348: {
349: if (net) {
350: net->priority = priority;
351: return YES;
352: }
353: return NO;
354: }
355:
2.36 frystyk 356: /* create_object
357: ** -------------
358: ** Creates an HTNet object
359: */
2.69 frystyk 360: PRIVATE HTNet * create_object (void)
2.36 frystyk 361: {
362: HTNet * me;
2.49 frystyk 363: if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
364: HT_OUTOFMEM("HTNet_new");
2.37 frystyk 365: me->tcpstate = TCP_BEGIN;
2.47 frystyk 366: if (!HTNetActive) HTNetActive = HTList_new();
2.36 frystyk 367: return me;
368: }
369:
2.37 frystyk 370: /* HTNet_new
371: ** ---------
372: ** This function creates a new HTNet object and assigns the socket number
373: ** to it. This is intended to be used when you are going to listen on a
374: ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
375: ** call any of the callback functions.
376: ** Returns new object or NULL on error
377: */
2.69 frystyk 378: PUBLIC HTNet * HTNet_new (SOCKET sockfd, HTRequest * request)
2.37 frystyk 379: {
2.69 frystyk 380: if (sockfd != INVSOC) {
381: HTNet * me;
382: if ((me = create_object()) == NULL) return NULL;
383: if (CORE_TRACE)
384: HTTrace("HTNet_new... Create empty Net object %p\n", me);
385: me->preemptive = HTRequest_preemptive(request);
386: me->priority = HTRequest_priority(request);
387: me->sockfd = sockfd;
388: me->request = request;
389: HTRequest_setNet(request, me);
390: return me;
391: }
392: if (CORE_TRACE) HTTrace("HTNet_new... Can't create empty Net object!\n");
393: return NULL;
2.37 frystyk 394: }
395:
2.67 frystyk 396: /* HTNet_newServer
397: ** ---------------
398: ** Create a new HTNet object as a new request to be handled. If we have
399: ** more than HTMaxActive connections already then return NO.
400: ** Returns YES if OK, else NO
2.37 frystyk 401: */
2.69 frystyk 402: PUBLIC BOOL HTNet_newServer (HTRequest * request, HTNet * net, char * access)
2.37 frystyk 403: {
404: HTProtocol * protocol;
2.67 frystyk 405: HTTransport * tp = NULL; /* added JTD:5/28/96 */
2.37 frystyk 406: if (!request) return NO;
407:
408: /* Find a protocol object for this access scheme */
2.46 frystyk 409: protocol = HTProtocol_find(request, access);
2.67 frystyk 410:
411: /* added - JTD:5/28/96 */
412: /* Find a transport object for this protocol */
413: tp = HTTransport_find(request, HTProtocol_transport(protocol));
414: if (tp == NULL) {
415: if (CORE_TRACE) HTTrace("HTNet....... NO TRANSPORT OBJECT\n");
416: return NO;
417: }
418: /* end of additions - JTD:5/28/96 */
419:
2.69 frystyk 420: /* Fill out the net object and bind it to the request object */
421: net->preemptive = (HTProtocol_preemptive(protocol) || request->preemptive);
422: net->protocol = protocol;
423: net->transport = tp; /* added - JTD:5/28/96 */
424: net->priority = HTRequest_priority(request);
425: net->request = request;
426: HTRequest_setNet(request, net);
427: if (!(net->cbf = HTProtocol_server(protocol))) {
2.67 frystyk 428: if (CORE_TRACE) HTTrace("HTNet_new... NO CALL BACK FUNCTION!\n");
429: return NO;
2.37 frystyk 430: }
431: request->retrys++;
432:
433: /* Start the server request */
2.69 frystyk 434: HTList_addObject(HTNetActive, (void *) net);
2.58 hallam 435: if (CORE_TRACE)
2.69 frystyk 436: HTTrace("HTNet_new... starting SERVER request %p with net object %p\n", request, net);
437: (*(net->cbf))(net->sockfd, request, FD_NONE);
2.37 frystyk 438: return YES;
439: }
2.36 frystyk 440:
2.30 frystyk 441: /* HTNet_new
442: ** ---------
2.23 frystyk 443: ** Create a new HTNet object as a new request to be handled. If we have
444: ** more than HTMaxActive connections already then put this into the
445: ** pending queue, else start the request by calling the call back
446: ** function registered with this access method.
447: ** Returns YES if OK, else NO
448: */
2.37 frystyk 449: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23 frystyk 450: {
2.33 frystyk 451: int status;
2.59 frystyk 452: HTNet * me = NULL;
453: HTProtocol * protocol = NULL;
454: HTTransport * tp = NULL;
2.37 frystyk 455: char * physical = NULL;
2.27 frystyk 456: if (!request) return NO;
2.33 frystyk 457: /*
458: ** First we do all the "BEFORE" callbacks in order to see if we are to
459: ** continue with this request or not. If we receive a callback status
460: ** that is NOT HT_OK then jump directly to the after callbacks and return
461: */
2.58 hallam 462: if ((status = HTNet_callBefore(request, HT_OK)) != HT_OK) {
463: HTNet_callAfter(request, status);
2.33 frystyk 464: return YES;
465: }
466:
2.36 frystyk 467: /*
468: ** If no translation was provided by the application then use the anchor
469: ** address directly
470: */
2.71 frystyk 471: if (!(physical = HTAnchor_physical(request->anchor))) {
2.36 frystyk 472: char * addr = HTAnchor_address((HTAnchor *) request->anchor);
2.58 hallam 473: if (CORE_TRACE) HTTrace("HTNet New... Using default address\n");
2.36 frystyk 474: HTAnchor_setPhysical(request->anchor, addr);
2.37 frystyk 475: physical = HTAnchor_physical(request->anchor);
2.49 frystyk 476: HT_FREE(addr);
2.33 frystyk 477: }
478:
2.37 frystyk 479: /* Find a protocol object for this access scheme */
480: {
481: char * access = HTParse(physical, "", PARSE_ACCESS);
482: if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.58 hallam 483: if (CORE_TRACE) HTTrace("HTNet_new... NO PROTOCOL OBJECT\n");
2.49 frystyk 484: HT_FREE(access);
2.37 frystyk 485: return NO;
486: }
2.49 frystyk 487: HT_FREE(access);
2.37 frystyk 488: }
2.59 frystyk 489:
490: /* Find a transport object for this protocol */
491: tp = HTTransport_find(request, HTProtocol_transport(protocol));
492: if (tp == NULL) {
2.60 frystyk 493: if (CORE_TRACE) HTTrace("HTNet....... NO TRANSPORT OBJECT\n");
2.59 frystyk 494: return NO;
495: }
496:
2.23 frystyk 497: /* Create new net object and bind it to the request object */
2.69 frystyk 498: if ((me = create_object()) == NULL) return NO;
2.45 frystyk 499: me->preemptive = (HTProtocol_preemptive(protocol) || request->preemptive);
2.69 frystyk 500: me->priority = HTRequest_priority(request);
2.23 frystyk 501: me->sockfd = INVSOC;
2.59 frystyk 502: me->protocol = protocol;
503: me->transport = tp;
2.69 frystyk 504: me->request = request;
505: HTRequest_setNet(request, me);
2.37 frystyk 506: if (!(me->cbf = HTProtocol_client(protocol))) {
2.58 hallam 507: if (CORE_TRACE) HTTrace("HTNet_new... NO CALL BACK FUNCTION!\n");
2.49 frystyk 508: HT_FREE(me);
2.23 frystyk 509: return NO;
510: }
2.25 frystyk 511: request->retrys++;
2.23 frystyk 512:
513: /*
514: ** Check if we can start the request, else put it into pending queue
515: ** If so then call the call back function associated with the anchor.
516: ** We use the INVSOC as we don't have a valid socket yet!
517: */
518: if (HTList_count(HTNetActive) < HTMaxActive) {
519: HTList_addObject(HTNetActive, (void *) me);
2.58 hallam 520: if (CORE_TRACE)
2.50 eric 521: HTTrace("HTNet_new... starting request %p (retry=%d) with net object %p\n",
2.43 frystyk 522: request, request->retrys, me);
2.25 frystyk 523: (*(me->cbf))(me->sockfd, request, FD_NONE);
2.23 frystyk 524: } else {
2.35 frystyk 525: HTAlertCallback *cbf = HTAlert_find(HT_PROG_WAIT);
2.23 frystyk 526: if (!HTNetPending) HTNetPending = HTList_new();
2.58 hallam 527: if (CORE_TRACE)
2.50 eric 528: HTTrace("HTNet_new... request %p registered as pending\n",
2.25 frystyk 529: request);
2.35 frystyk 530: if (cbf) (*cbf)(request, HT_PROG_WAIT, HT_MSG_NULL, NULL, NULL, NULL);
2.25 frystyk 531: HTList_addObject(HTNetPending, (void *) me);
2.23 frystyk 532: }
2.36 frystyk 533: return YES;
534: }
535:
2.23 frystyk 536: /* delete_object
537: ** -------------
538: ** Deletes an HTNet object
2.40 frystyk 539: ** Return YES if OK, else NO
2.15 frystyk 540: */
2.23 frystyk 541: PRIVATE BOOL delete_object (HTNet *net, int status)
2.15 frystyk 542: {
2.58 hallam 543: if (CORE_TRACE)
2.50 eric 544: HTTrace("HTNet_delete Remove net object %p\n", net);
2.23 frystyk 545: if (net) {
546:
547: /* Free stream with data FROM network to application */
2.59 frystyk 548: #if 0
2.23 frystyk 549: if (net->target) {
550: if (status == HT_INTERRUPTED)
551: (*net->target->isa->abort)(net->target, NULL);
552: else
553: (*net->target->isa->_free)(net->target);
2.48 frystyk 554: net->target = NULL;
2.23 frystyk 555: }
2.59 frystyk 556: #endif
2.23 frystyk 557:
558: /* Close socket */
2.62 eric 559: if (net->channel) {
2.64 eric 560: HTEvent_unregister(net->sockfd, (SockOps) FD_ALL);
2.59 frystyk 561: if (HTHost_channel(net->host) == NULL) {
562: if (CORE_TRACE)
563: HTTrace("HTNet_delete closing %d\n", net->sockfd);
2.70 frystyk 564: HTChannel_downSemaphore(net->channel);
565: HTChannel_delete(net->channel, status);
2.24 frystyk 566: } else {
2.59 frystyk 567: if (CORE_TRACE)
568: HTTrace("HTNet_delete keeping %d\n", net->sockfd);
2.25 frystyk 569: /* Here we should probably use a low priority */
2.70 frystyk 570: HTChannel_delete(net->channel, status);
2.64 eric 571: HTEvent_register(net->sockfd, 0, (SockOps) FD_READ,
2.59 frystyk 572: HTHost_catchClose, net->priority);
2.24 frystyk 573: }
2.63 eric 574: net->channel = NULL;
2.23 frystyk 575: }
2.69 frystyk 576: HTRequest_setNet(net->request, NULL); /* Break link to request */
2.49 frystyk 577: HT_FREE(net);
2.23 frystyk 578: return status ? NO : YES;
579: }
580: return NO;
581: }
582:
583: /* HTNet_delete
584: ** ------------
585: ** Deletes the HTNet object from the list of active requests and calls
586: ** any registered call back functions IF not the status is HT_IGNORE.
587: ** This is used if we have internal requests that the app doesn't know
588: ** about. We also see if we have pending requests that can be started
589: ** up now when we have a socket free.
590: ** The callback functions are called in the reverse order of which they
591: ** were registered (last one first)
2.40 frystyk 592: ** Return YES if OK, else NO
2.23 frystyk 593: */
594: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
595: {
2.58 hallam 596: if (CORE_TRACE)
2.50 eric 597: HTTrace("HTNetDelete. Object and call callback functions\n");
2.23 frystyk 598: if (HTNetActive && net) {
2.36 frystyk 599: SOCKET cs = net->sockfd; /* Current sockfd */
2.23 frystyk 600:
601: /* Remove object and call callback functions */
602: HTRequest *request = net->request;
2.42 frystyk 603: if (HTList_removeObject(HTNetActive, (void *) net) != YES)
2.58 hallam 604: if (CORE_TRACE)
2.50 eric 605: HTTrace("HTNetDelete. %p not registered!\n", net);
2.23 frystyk 606: delete_object(net, status);
2.61 eric 607: HTNet_callAfter(request, status);
2.23 frystyk 608:
2.25 frystyk 609: /*
610: ** See first if we have a persistent request queued up for this socket
611: ** If not then see if there is a pending request
612: */
613: if (HTNetPersistent) {
614: HTList *cur = HTNetPersistent;
615: HTNet *next;
616: while ((next = (HTNet *) HTList_nextObject(cur))) {
617: if (next->sockfd == cs) {
2.58 hallam 618: if (CORE_TRACE)
2.50 eric 619: HTTrace("HTNet delete Launch request %p on WARM socket %d (net object %p)\n",
2.39 frystyk 620: next->request, next->sockfd, next);
2.28 frystyk 621: HTList_addObject(HTNetActive, (void *) next);
622: HTList_removeObject(HTNetPersistent, (void *) next);
2.41 frystyk 623: (*(next->cbf))(next->sockfd, next->request, FD_WRITE);
2.25 frystyk 624: break;
625: }
626: }
627: } else if (HTList_count(HTNetActive) < HTMaxActive &&
628: HTList_count(HTNetPending)) {
2.23 frystyk 629: HTNet *next = (HTNet *) HTList_removeFirstObject(HTNetPending);
630: if (next) {
631: HTList_addObject(HTNetActive, (void *) next);
2.58 hallam 632: if (CORE_TRACE)
2.50 eric 633: HTTrace("HTNet delete launch PENDING request %p\n",
2.23 frystyk 634: next->request);
635: (*(next->cbf))(INVSOC, next->request, FD_NONE);
636: }
637: }
638: return YES;
639: }
640: return NO;
641: }
642:
643: /* HTNet_deleteAll
644: ** ---------------
645: ** Deletes all HTNet object that might either be active or pending
2.25 frystyk 646: ** We DO NOT call the call back functions - A crude way of saying goodbye!
2.23 frystyk 647: */
648: PUBLIC BOOL HTNet_deleteAll (void)
649: {
2.58 hallam 650: if (CORE_TRACE)
2.50 eric 651: HTTrace("HTNetDelete. Remove all Net objects, NO callback\n");
2.25 frystyk 652: if (HTNetPersistent) {
653: HTList *cur = HTNetPersistent;
654: HTNet *pres;
655: while ((pres = (HTNet *) HTList_nextObject(cur))) {
656: pres->sockfd = INVSOC; /* Don't close it more than once */
657: delete_object(pres, HT_INTERRUPTED);
658: }
659: HTList_delete(HTNetPersistent);
660: HTNetPersistent = NULL;
661: }
2.23 frystyk 662: if (HTNetPending) {
663: HTList *cur = HTNetPending;
664: HTNet *pres;
665: while ((pres = (HTNet *) HTList_nextObject(cur)))
666: delete_object(pres, HT_INTERRUPTED);
667: HTList_delete(HTNetPending);
668: HTNetPending = NULL;
669: }
670: if (HTNetActive) {
671: HTList *cur = HTNetActive;
672: HTNet *pres;
673: while ((pres = (HTNet *) HTList_nextObject(cur)))
674: delete_object(pres, HT_INTERRUPTED);
675: HTList_delete(HTNetActive);
676: HTNetActive = NULL;
677: }
678: return NO;
2.15 frystyk 679: }
680:
2.25 frystyk 681: /* HTNet_wait
682: ** ----------
683: ** Let a net object wait for a persistent socket. It will be launched
684: ** from the HTNet_delete() function
2.40 frystyk 685: ** Return YES if OK, else NO
2.25 frystyk 686: */
687: PUBLIC BOOL HTNet_wait (HTNet *net)
688: {
689: if (net) {
2.58 hallam 690: if (CORE_TRACE)
2.50 eric 691: HTTrace("HTNet_wait.. request %p is waiting for presistent socket %d\n",
2.40 frystyk 692: net->request, net->sockfd);
693:
694: /* Take it out of the active queue and add it to persistent queue */
695: if (HTList_removeObject(HTNetActive, (void *) net) != YES) {
2.58 hallam 696: if (CORE_TRACE) HTTrace("HTNet_wait.. not registered!\n");
2.40 frystyk 697: return NO;
698: }
2.25 frystyk 699: if (!HTNetPersistent) HTNetPersistent = HTList_new();
2.40 frystyk 700: return HTList_addObject(HTNetPersistent, (void *) net);
2.25 frystyk 701: }
702: return NO;
703: }
704:
2.23 frystyk 705: /* ------------------------------------------------------------------------- */
706: /* Killing requests */
707: /* ------------------------------------------------------------------------- */
708:
709: /* HTNet_kill
710: ** ----------
711: ** Kill the request by calling the call back function with a request for
712: ** closing the connection. Does not remove the object. This is done by
713: ** HTNet_delete() function which is called by the load routine.
714: ** Returns OK if success, NO on error
715: */
716: PUBLIC BOOL HTNet_kill (HTNet * me)
717: {
718: if (HTNetActive && me) {
2.25 frystyk 719: HTList *cur = HTNetActive;
2.23 frystyk 720: HTNet *pres;
2.25 frystyk 721: while ((pres = (HTNet *) HTList_nextObject(cur))) {
2.23 frystyk 722: if (pres == me) {
2.25 frystyk 723: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 724: return YES;
725: }
726: }
727: }
2.58 hallam 728: if (CORE_TRACE)
2.50 eric 729: HTTrace("HTNet_kill.. object %p is not registered\n", me);
2.23 frystyk 730: return NO;
731: }
732:
733: /* HTNet_killAll
734: ** -------------
735: ** Kills all registered (active+pending) requests by calling the call
736: ** back function with a request for closing the connection. We do not
737: ** remove the HTNet object as it is done by HTNet_delete().
738: ** Returns OK if success, NO on error
739: */
740: PUBLIC BOOL HTNet_killAll (void)
741: {
742: HTNet *pres;
2.58 hallam 743: if (CORE_TRACE)
2.50 eric 744: HTTrace("HTNet_kill.. ALL registered requests!!!\n");
2.23 frystyk 745:
2.25 frystyk 746: /* We start off in persistent queue so we avoid racing */
747: if (HTNetPersistent) {
748: while ((pres = (HTNet *) HTList_lastObject(HTNetPersistent)) != NULL) {
749: pres->sockfd = INVSOC;
750: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
751: HTList_removeObject(HTNetPersistent, pres);
752: }
753: }
2.23 frystyk 754: if (HTNetPending) {
755: while ((pres = (HTNet *) HTList_lastObject(HTNetPending)) != NULL) {
2.25 frystyk 756: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 757: HTList_removeObject(HTNetPending, pres);
758: }
759: }
760: if (HTNetActive) {
761: while ((pres = (HTNet *) HTList_lastObject(HTNetActive)) != NULL)
2.25 frystyk 762: (*(pres->cbf))(pres->sockfd, pres->request, FD_CLOSE);
2.23 frystyk 763: }
764: return YES;
765: }
2.38 frystyk 766:
767: /* ------------------------------------------------------------------------- */
2.59 frystyk 768: /* Connection Specifics */
769: /* ------------------------------------------------------------------------- */
770:
771: /* HTNet_Persistent
772: ** ----------------
773: ** Check whether the net object handles persistent connections
774: ** If we have a DNS entry then check that as well.
775: */
776: PUBLIC BOOL HTNet_persistent (HTNet * net)
777: {
778: return (net && HTHost_isPersistent(net->host));
779: }
780:
781: /* HTNet_persistent
782: ** ----------------
783: ** Set the net object to handle persistent connections
784: ** If we also have a DNS entry then update that as well
785: */
786: PUBLIC BOOL HTNet_setPersistent (HTNet * net, BOOL persistent)
787: {
788: if (net) {
2.60 frystyk 789: if (CORE_TRACE) HTTrace("Net......... Persistent connection set %s\n",
2.59 frystyk 790: persistent ? "ON" : "OFF");
791: if (persistent)
792: HTHost_setChannel(net->host, net->channel);
793: else
794: HTHost_clearChannel(net->host);
795: }
796: return NO;
797: }
798:
799: /* ------------------------------------------------------------------------- */
2.38 frystyk 800: /* Data Access Methods */
801: /* ------------------------------------------------------------------------- */
2.66 frystyk 802:
803: /*
804: ** Context pointer to be used in context call back function
805: */
806: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
807: {
808: if (net) {
809: net->context = context;
810: return YES;
811: }
812: return NO;
813: }
814:
815: PUBLIC void * HTNet_context (HTNet * net)
816: {
817: return net ? net->context : NULL;
818: }
2.38 frystyk 819:
820: /*
2.60 frystyk 821: ** Get and set the socket number
822: */
823: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
824: {
825: if (net) {
826: net->sockfd = sockfd;
827: return YES;
828: }
829: return NO;
830: }
831:
832: PUBLIC SOCKET HTNet_socket (HTNet * net)
833: {
834: return (net ? net->sockfd : INVSOC);
2.69 frystyk 835: }
836:
837: /*
838: ** Get and set the HTRequest object
839: */
840: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
841: {
842: if (net && request) {
843: net->request = request;
844: return YES;
845: }
846: return NO;
847: }
848:
849: PUBLIC HTRequest * HTNet_request (HTNet * net)
850: {
851: return (net ? net->request : NULL);
2.60 frystyk 852: }
853:
854: /*
2.59 frystyk 855: ** Get and set the HTTransport object
2.38 frystyk 856: */
2.59 frystyk 857: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
2.38 frystyk 858: {
2.59 frystyk 859: if (net && tp) {
860: net->transport = tp;
2.38 frystyk 861: return YES;
862: }
863: return NO;
864: }
865:
2.59 frystyk 866: PUBLIC HTTransport * HTNet_transport (HTNet * net)
2.38 frystyk 867: {
2.59 frystyk 868: return (net ? net->transport : NULL);
2.38 frystyk 869: }
870:
2.55 frystyk 871: /*
2.59 frystyk 872: ** Get and set the HTChannel object
2.55 frystyk 873: */
2.59 frystyk 874: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55 frystyk 875: {
2.59 frystyk 876: if (net && channel) {
877: net->channel = channel;
2.55 frystyk 878: return YES;
879: }
880: return NO;
881: }
882:
2.59 frystyk 883: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55 frystyk 884: {
2.59 frystyk 885: return (net ? net->channel : NULL);
886: }
887:
888: /*
889: ** Get and set the HTHost object
890: */
891: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
892: {
893: if (net && host) {
894: net->host = host;
895: return YES;
896: }
897: return NO;
898: }
899:
900: PUBLIC HTHost * HTNet_host (HTNet * net)
901: {
902: return (net ? net->host : NULL);
903: }
904:
905: /*
906: ** Get and set the HTdns object
907: */
908: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
909: {
910: if (net && dns) {
911: net->dns = dns;
912: return YES;
913: }
914: return NO;
915: }
916:
917: PUBLIC HTdns * HTNet_dns (HTNet * net)
918: {
919: return (net ? net->dns : NULL);
920: }
921:
2.72 frystyk 922: PUBLIC int HTNet_home (HTNet * net)
923: {
924: return (net ? net->home : 0);
925: }
2.59 frystyk 926:
927: /*
928: ** Create the input stream and bind it to the channel
929: ** Please read the description in the HTIOStream module for the parameters
930: */
931: PUBLIC HTInputStream * HTNet_getInput (HTNet * net, HTStream * target,
932: void * param, int mode)
933: {
934: if (net && net->channel && net->transport) {
935: HTTransport * tp = net->transport;
936: HTChannel * ch = net->channel;
937: net->input = (*tp->input_new)(net, ch, target, param, mode);
938: HTChannel_setInput(ch, net->input, tp->mode);
939: return net->input;
940: }
2.60 frystyk 941: if (CORE_TRACE) HTTrace("Net......... Can't create input stream\n");
2.59 frystyk 942: return NULL;
943: }
944:
945: /*
946: ** Create the output stream and bind it to the channel
947: ** Please read the description in the HTIOStream module on the parameters
948: */
949: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * net, void * param, int mode)
950: {
951: if (net && net->request && net->channel && net->transport) {
952: HTTransport * tp = net->transport;
953: HTChannel * ch = net->channel;
954: HTOutputStream * output = (*tp->output_new)(net, ch, param, mode);
955: HTChannel_setOutput(ch, output, tp->mode);
956: return output;
957: }
2.60 frystyk 958: if (CORE_TRACE) HTTrace("Net......... Can't create output stream\n");
2.59 frystyk 959: return NULL;
2.55 frystyk 960: }
Webmaster