Annotation of libwww/Library/src/HTNet.c, revision 2.74
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.74 ! frystyk 6: ** @(#) $Id: HTNet.c,v 2.73 1996/08/08 02:16:53 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.74 ! frystyk 27: #include "HTHost.h"
! 28: #include "HTReq.h"
2.65 frystyk 29: #include "HTEvent.h"
2.23 frystyk 30: #include "HTStream.h"
2.24 frystyk 31: #include "HTNetMan.h" /* Implemented here */
2.1 frystyk 32:
2.23 frystyk 33: #ifndef HT_MAX_SOCKETS
34: #define HT_MAX_SOCKETS 6
35: #endif
36:
2.74 ! frystyk 37: #define HASH_SIZE 67
! 38:
2.33 frystyk 39: typedef struct _NetCall {
2.30 frystyk 40: HTNetCallback * cbf;
2.60 frystyk 41: void * param; /* Local context */
2.23 frystyk 42: int status; /* Status associated with this callback */
2.33 frystyk 43: } NetCall;
2.23 frystyk 44:
45: struct _HTStream {
2.52 frystyk 46: const HTStreamClass * isa;
2.23 frystyk 47: /* ... */
48: };
49:
2.33 frystyk 50: PRIVATE HTList *HTBefore = NULL; /* List of call back functions */
51: PRIVATE HTList *HTAfter = NULL; /* List of call back functions */
2.24 frystyk 52:
2.74 ! frystyk 53: PRIVATE int MaxActive = HT_MAX_SOCKETS; /* Max active requests */
! 54: PRIVATE int Active = 0; /* Counts open sockets */
! 55: PRIVATE int Persistent = 0; /* Counts persistent sockets */
2.1 frystyk 56:
2.74 ! frystyk 57: PRIVATE HTList ** NetTable = NULL; /* List of net objects */
! 58: PRIVATE int HTNetCount = 0; /* Counting elements in table */
2.23 frystyk 59:
60: /* ------------------------------------------------------------------------- */
2.74 ! frystyk 61: /* BEFORE and AFTER filters */
2.23 frystyk 62: /* ------------------------------------------------------------------------- */
63:
2.33 frystyk 64: /* HTNetCall_add
65: ** -------------
66: ** Register a call back function that is to be called on every request.
67: ** Several call back functions can be registered
2.23 frystyk 68: ** in which case all of them are called in the order of which they
69: ** were registered.
70: **
71: ** The status signifies which call back function to call depending of the
72: ** result of the request. This can be
73: **
74: ** HT_ERROR An error occured
75: ** HT_LOADED The document was loaded
76: ** HT_NO_DATA OK, but no data
2.33 frystyk 77: ** HT_REDIRECT If we received a redirection
2.23 frystyk 78: ** HT_RETRY Retry request after at a later time
79: ** HT_ALL All of above
80: */
2.60 frystyk 81: PUBLIC BOOL HTNetCall_add (HTList * list, HTNetCallback * cbf,
82: void * param, int status)
2.23 frystyk 83: {
2.58 hallam 84: if (CORE_TRACE)
2.74 ! frystyk 85: HTTrace("Net Filter.. Add %p with context %p\n",
2.60 frystyk 86: (void *) cbf, param);
2.33 frystyk 87: if (list && cbf) {
2.49 frystyk 88: NetCall *me;
89: if ((me = (NetCall *) HT_CALLOC(1, sizeof(NetCall))) == NULL)
90: HT_OUTOFMEM("HTNetCall_add");
2.33 frystyk 91: me->cbf = cbf;
2.60 frystyk 92: me->param = param;
2.33 frystyk 93: me->status = status;
94: return HTList_addObject(list, (void *) me);
2.23 frystyk 95: }
96: return NO;
97: }
98:
2.33 frystyk 99: /* HTNetCall_delete
100: ** ----------------
101: ** Unregister a call back function from a list
2.23 frystyk 102: */
2.33 frystyk 103: PUBLIC BOOL HTNetCall_delete (HTList * list, HTNetCallback *cbf)
2.23 frystyk 104: {
2.74 ! frystyk 105: if (CORE_TRACE) HTTrace("Net Filter.. Delete %p\n", (void *) cbf);
2.33 frystyk 106: if (list && cbf) {
107: HTList *cur = list;
108: NetCall *pres;
109: while ((pres = (NetCall *) HTList_nextObject(cur))) {
2.23 frystyk 110: if (pres->cbf == cbf) {
2.33 frystyk 111: HTList_removeObject(list, (void *) pres);
2.49 frystyk 112: HT_FREE(pres);
2.23 frystyk 113: return YES;
114: }
115: }
116: }
117: return NO;
118: }
2.1 frystyk 119:
2.33 frystyk 120: /* HTNetCall_deleteAll
2.23 frystyk 121: ** -------------------
122: ** Unregisters all call back functions
123: */
2.33 frystyk 124: PUBLIC BOOL HTNetCall_deleteAll (HTList * list)
2.23 frystyk 125: {
2.74 ! frystyk 126: if (CORE_TRACE) HTTrace("Net Filter. Delete All filters\n");
2.33 frystyk 127: if (list) {
128: HTList *cur = list;
129: NetCall *pres;
130: while ((pres = (NetCall *) HTList_nextObject(cur))) {
131: HTList_removeObject(list, (void *) pres);
2.49 frystyk 132: HT_FREE(pres);
2.23 frystyk 133: }
2.33 frystyk 134: HTList_delete(list);
2.23 frystyk 135: return YES;
136: }
137: return NO;
138: }
139:
2.33 frystyk 140: /* HTNetCall_execute
141: ** -----------------
2.23 frystyk 142: ** Call all the call back functions registered in the list IF not the
143: ** status is HT_IGNORE.
144: ** The callback functions are called in the order of which they
145: ** were registered. At the moment an application callback function is
146: ** called, it can free the request object - it is no longer used by the
147: ** Library.
2.33 frystyk 148: ** Returns what the last callback function returns
2.23 frystyk 149: */
2.33 frystyk 150: PUBLIC int HTNetCall_execute (HTList * list, HTRequest * request, int status)
2.23 frystyk 151: {
2.33 frystyk 152: int ret = HT_OK;
153: if (list && request && status != HT_IGNORE) {
154: int cnt = HTList_count(list);
2.23 frystyk 155: while (--cnt >= 0) {
2.33 frystyk 156: NetCall *pres = (NetCall *) HTList_objectAt(list, cnt);
2.23 frystyk 157: if (pres && (pres->status == status || pres->status == HT_ALL)) {
2.58 hallam 158: if (CORE_TRACE)
2.74 ! frystyk 159: HTTrace("Net Filter.. %p (request=%p, status=%d)\n",
2.23 frystyk 160: (void *) pres->cbf, request, status);
2.60 frystyk 161: if ((ret=(*(pres->cbf))(request, pres->param,status)) != HT_OK)
162: break;
2.23 frystyk 163: }
164: }
2.1 frystyk 165: }
2.33 frystyk 166: return ret;
167: }
168:
169: /*
170: ** Global set of callback functions BEFORE the request is issued
171: ** list can be NULL
172: */
173: PUBLIC BOOL HTNet_setBefore (HTList *list)
174: {
2.57 eric 175: /* if (HTBefore) HTNetCall_deleteAll(HTBefore); */
2.33 frystyk 176: HTBefore = list;
177: return YES;
178: }
179:
180: PUBLIC HTList * HTNet_before (void)
181: {
182: return HTBefore;
183: }
184:
185: PUBLIC int HTNet_callBefore (HTRequest *request, int status)
186: {
2.58 hallam 187: int ret;
188: BOOL override = NO;
189: HTList * befores;
190:
191: if ((befores = HTRequest_before(request, &override))) {
192: if ((ret = HTNetCall_execute(befores, request, status)) != HT_OK)
193: return ret;
194: }
195: if (override)
196: return HT_OK;
2.33 frystyk 197: return HTNetCall_execute(HTBefore, request, status);
198: }
199:
2.60 frystyk 200: PUBLIC BOOL HTNetCall_addBefore (HTNetCallback * cbf, void * param, int status)
2.33 frystyk 201: {
202: if (!HTBefore) HTBefore = HTList_new();
2.60 frystyk 203: return HTNetCall_add(HTBefore, cbf, param, status);
2.33 frystyk 204: }
205:
2.73 frystyk 206: PUBLIC BOOL HTNetCall_deleteBefore (HTNetCallback * cbf)
207: {
208: return HTNetCall_delete(HTBefore, cbf);
209: }
210:
2.33 frystyk 211: /*
212: ** Global set of callback functions AFTER the request is issued
213: ** list can be NULL
214: */
215: PUBLIC BOOL HTNet_setAfter (HTList *list)
216: {
2.57 eric 217: /* if (HTAfter) HTNetCall_deleteAll(HTAfter); */
2.33 frystyk 218: HTAfter = list;
219: return YES;
220: }
221:
222: PUBLIC HTList * HTNet_after (void)
223: {
224: return HTAfter;
225: }
226:
227: PUBLIC int HTNet_callAfter (HTRequest *request, int status)
228: {
2.58 hallam 229: int ret;
230: BOOL override = NO;
231: HTList * afters;
232:
233: if ((afters = HTRequest_after(request, &override))) {
234: if ((ret = HTNetCall_execute(afters, request, status)) != HT_OK)
235: return ret;
236: }
237: if (override)
238: return HT_OK;
2.33 frystyk 239: return HTNetCall_execute(HTAfter, request, status);
240: }
241:
2.60 frystyk 242: PUBLIC BOOL HTNetCall_addAfter (HTNetCallback * cbf, void * param, int status)
2.33 frystyk 243: {
244: if (!HTAfter) HTAfter = HTList_new();
2.60 frystyk 245: return HTNetCall_add(HTAfter, cbf, param, status);
2.73 frystyk 246: }
247:
248: PUBLIC BOOL HTNetCall_deleteAfter (HTNetCallback * cbf)
249: {
250: return HTNetCall_delete(HTBefore, cbf);
2.1 frystyk 251: }
252:
2.23 frystyk 253: /* ------------------------------------------------------------------------- */
2.74 ! frystyk 254: /* Socket Management */
2.23 frystyk 255: /* ------------------------------------------------------------------------- */
2.1 frystyk 256:
2.74 ! frystyk 257: PUBLIC int HTNet_maxSocket (void)
! 258: {
! 259: return MaxActive;
! 260: }
! 261:
! 262: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
! 263: {
! 264: if (newmax > 0) {
! 265: MaxActive = newmax;
! 266: return YES;
! 267: }
! 268: return NO;
! 269: }
! 270:
! 271: PUBLIC void HTNet_increaseSocket (void)
! 272: {
! 273: Active++;
! 274: if (CORE_TRACE) HTTrace("Net Manager. %d open sockets\n", Active);
! 275: }
! 276:
! 277: PUBLIC void HTNet_decreaseSocket (void)
! 278: {
! 279: if (--Active < 0) Active = 0;
! 280: if (CORE_TRACE) HTTrace("Net Manager. %d open sockets\n", Active);
! 281: }
! 282:
! 283: PUBLIC int HTNet_availableSockets (void)
! 284: {
! 285: int available = MaxActive - Active;
! 286: return available > 0 ? available : 0;
! 287: }
! 288:
! 289: PUBLIC void HTNet_increasePersistentSocket (void)
! 290: {
! 291: Persistent++;
! 292: if (CORE_TRACE) HTTrace("Net Manager. %d persistent sockets\n", Persistent);
! 293: }
! 294:
! 295: PUBLIC void HTNet_decreasePersistentSocket (void)
2.23 frystyk 296: {
2.74 ! frystyk 297: if (--Persistent < 0) Persistent = 0;
! 298: if (CORE_TRACE) HTTrace("Net Manager. %d persistent sockets\n", Persistent);
2.23 frystyk 299: }
2.17 frystyk 300:
2.74 ! frystyk 301: PUBLIC int HTNet_availablePersistentSockets (void)
2.28 frystyk 302: {
2.74 ! frystyk 303: int available = MaxActive - 2 - Persistent;
! 304: return available > 0 ? available : 0;
2.28 frystyk 305: }
306:
2.74 ! frystyk 307: /*
! 308: ** Returns whether there are any Net objects pending or active
2.40 frystyk 309: */
2.74 ! frystyk 310: PUBLIC BOOL HTNet_isIdle (void)
2.40 frystyk 311: {
2.74 ! frystyk 312: return (HTNetCount > 0);
2.40 frystyk 313: }
314:
2.74 ! frystyk 315: PUBLIC BOOL HTNet_isEmpty (void)
2.1 frystyk 316: {
2.74 ! frystyk 317: return (HTNetCount <= 0);
2.1 frystyk 318: }
319:
2.23 frystyk 320: /* ------------------------------------------------------------------------- */
321: /* Creation and deletion methods */
322: /* ------------------------------------------------------------------------- */
323:
2.74 ! frystyk 324: PRIVATE HTNet * create_object (void)
! 325: {
! 326: static int net_hash = 0;
! 327: HTNet * me = NULL;
! 328:
! 329: /* Create new object */
! 330: if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
! 331: HT_OUTOFMEM("HTNet_new");
! 332: me->hash = net_hash++ % HASH_SIZE;
! 333: me->tcpstate = TCP_BEGIN;
! 334:
! 335: /* Insert into hash table */
! 336: if (!NetTable) {
! 337: if ((NetTable = (HTList **) HT_CALLOC(HASH_SIZE, sizeof(HTList *))) == NULL)
! 338: HT_OUTOFMEM("create_object");
! 339: }
! 340: if (!NetTable[me->hash]) NetTable[me->hash] = HTList_new();
! 341: HTList_addObject(NetTable[me->hash], (void *) me);
! 342: HTNetCount++;
! 343: if (CORE_TRACE)
! 344: HTTrace("Net Object.. %p created with hash %d\n",me, me->hash);
! 345: return me;
! 346: }
! 347:
2.27 frystyk 348: /* HTNet_duplicate
349: ** ---------------
350: ** Creates a new HTNet object as a duplicate of the same request.
351: ** Returns YES if OK, else NO
352: ** BUG: We do not check if we have a socket free!
353: */
2.43 frystyk 354: PUBLIC HTNet * HTNet_dup (HTNet * src)
2.27 frystyk 355: {
2.74 ! frystyk 356: if (src) {
! 357: HTNet * me;
! 358: if ((me = create_object()) == NULL) return NULL;
! 359: if (CORE_TRACE) HTTrace("Net Object.. Duplicated %p\n", src);
! 360: memcpy((void *) me, src, sizeof(HTNet));
! 361: return me;
! 362: }
! 363: return NULL;
2.27 frystyk 364: }
365:
2.74 ! frystyk 366: /*
! 367: ** Start a Net obejct by calling the protocol module.
2.30 frystyk 368: */
2.74 ! frystyk 369: PUBLIC BOOL HTNet_start (HTNet * net)
2.30 frystyk 370: {
2.74 ! frystyk 371: if (net && net->cbf && net->request) {
! 372: if (CORE_TRACE) HTTrace("Net Object.. Launching %p\n", net);
! 373: HTEvent_unregister(net->sockfd, (SockOps) FD_ALL);
! 374: (*(net->cbf))(net->sockfd, net->request, FD_NONE);
2.30 frystyk 375: return YES;
376: }
377: return NO;
378: }
379:
2.37 frystyk 380: /* HTNet_new
381: ** ---------
382: ** This function creates a new HTNet object and assigns the socket number
383: ** to it. This is intended to be used when you are going to listen on a
384: ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
385: ** call any of the callback functions.
386: ** Returns new object or NULL on error
387: */
2.69 frystyk 388: PUBLIC HTNet * HTNet_new (SOCKET sockfd, HTRequest * request)
2.37 frystyk 389: {
2.69 frystyk 390: if (sockfd != INVSOC) {
391: HTNet * me;
392: if ((me = create_object()) == NULL) return NULL;
393: me->preemptive = HTRequest_preemptive(request);
394: me->priority = HTRequest_priority(request);
395: me->sockfd = sockfd;
396: me->request = request;
397: HTRequest_setNet(request, me);
398: return me;
399: }
2.74 ! frystyk 400: if (CORE_TRACE) HTTrace("Net Object.. Can't create empty Net object!\n");
2.69 frystyk 401: return NULL;
2.37 frystyk 402: }
403:
2.67 frystyk 404: /* HTNet_newServer
405: ** ---------------
406: ** Create a new HTNet object as a new request to be handled. If we have
2.74 ! frystyk 407: ** more than MaxActive connections already then return NO.
2.67 frystyk 408: ** Returns YES if OK, else NO
2.37 frystyk 409: */
2.69 frystyk 410: PUBLIC BOOL HTNet_newServer (HTRequest * request, HTNet * net, char * access)
2.37 frystyk 411: {
412: HTProtocol * protocol;
2.67 frystyk 413: HTTransport * tp = NULL; /* added JTD:5/28/96 */
2.37 frystyk 414: if (!request) return NO;
415:
416: /* Find a protocol object for this access scheme */
2.46 frystyk 417: protocol = HTProtocol_find(request, access);
2.67 frystyk 418:
419: /* added - JTD:5/28/96 */
420: /* Find a transport object for this protocol */
421: tp = HTTransport_find(request, HTProtocol_transport(protocol));
422: if (tp == NULL) {
2.74 ! frystyk 423: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT OBJECT\n");
2.67 frystyk 424: return NO;
425: }
426: /* end of additions - JTD:5/28/96 */
427:
2.69 frystyk 428: /* Fill out the net object and bind it to the request object */
2.74 ! frystyk 429: net->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.69 frystyk 430: net->protocol = protocol;
431: net->transport = tp; /* added - JTD:5/28/96 */
432: net->priority = HTRequest_priority(request);
433: net->request = request;
434: HTRequest_setNet(request, net);
435: if (!(net->cbf = HTProtocol_server(protocol))) {
2.74 ! frystyk 436: if (CORE_TRACE) HTTrace("Net Object.. NO CALL BACK FUNCTION!\n");
2.67 frystyk 437: return NO;
2.37 frystyk 438: }
2.74 ! frystyk 439:
! 440: /* Increase the number of retrys for this download */
! 441: HTRequest_addRetry(request);
2.37 frystyk 442:
443: /* Start the server request */
2.58 hallam 444: if (CORE_TRACE)
2.74 ! frystyk 445: HTTrace("Net Object.. starting SERVER request %p with net object %p\n", request, net);
2.69 frystyk 446: (*(net->cbf))(net->sockfd, request, FD_NONE);
2.37 frystyk 447: return YES;
448: }
2.36 frystyk 449:
2.30 frystyk 450: /* HTNet_new
451: ** ---------
2.23 frystyk 452: ** Create a new HTNet object as a new request to be handled. If we have
2.74 ! frystyk 453: ** more than MaxActive connections already then put this into the
2.23 frystyk 454: ** pending queue, else start the request by calling the call back
455: ** function registered with this access method.
456: ** Returns YES if OK, else NO
457: */
2.37 frystyk 458: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23 frystyk 459: {
2.74 ! frystyk 460: HTParentAnchor * anchor = HTRequest_anchor(request);
2.59 frystyk 461: HTNet * me = NULL;
462: HTProtocol * protocol = NULL;
463: HTTransport * tp = NULL;
2.37 frystyk 464: char * physical = NULL;
2.74 ! frystyk 465: int status;
2.27 frystyk 466: if (!request) return NO;
2.33 frystyk 467: /*
468: ** First we do all the "BEFORE" callbacks in order to see if we are to
469: ** continue with this request or not. If we receive a callback status
470: ** that is NOT HT_OK then jump directly to the after callbacks and return
471: */
2.58 hallam 472: if ((status = HTNet_callBefore(request, HT_OK)) != HT_OK) {
473: HTNet_callAfter(request, status);
2.33 frystyk 474: return YES;
475: }
476:
2.36 frystyk 477: /*
478: ** If no translation was provided by the application then use the anchor
479: ** address directly
480: */
2.74 ! frystyk 481: if (!(physical = HTAnchor_physical(anchor))) {
! 482: char * addr = HTAnchor_address((HTAnchor *) anchor);
! 483: if (CORE_TRACE) HTTrace("Net Object.. Using default address\n");
! 484: HTAnchor_setPhysical(anchor, addr);
! 485: physical = HTAnchor_physical(anchor);
2.49 frystyk 486: HT_FREE(addr);
2.33 frystyk 487: }
488:
2.37 frystyk 489: /* Find a protocol object for this access scheme */
490: {
491: char * access = HTParse(physical, "", PARSE_ACCESS);
492: if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.74 ! frystyk 493: if (CORE_TRACE) HTTrace("Net Object.. NO PROTOCOL OBJECT\n");
2.49 frystyk 494: HT_FREE(access);
2.37 frystyk 495: return NO;
496: }
2.49 frystyk 497: HT_FREE(access);
2.37 frystyk 498: }
2.59 frystyk 499:
500: /* Find a transport object for this protocol */
501: tp = HTTransport_find(request, HTProtocol_transport(protocol));
502: if (tp == NULL) {
2.74 ! frystyk 503: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT OBJECT\n");
2.59 frystyk 504: return NO;
505: }
506:
2.23 frystyk 507: /* Create new net object and bind it to the request object */
2.69 frystyk 508: if ((me = create_object()) == NULL) return NO;
2.74 ! frystyk 509: me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.69 frystyk 510: me->priority = HTRequest_priority(request);
2.23 frystyk 511: me->sockfd = INVSOC;
2.59 frystyk 512: me->protocol = protocol;
513: me->transport = tp;
2.69 frystyk 514: me->request = request;
515: HTRequest_setNet(request, me);
2.37 frystyk 516: if (!(me->cbf = HTProtocol_client(protocol))) {
2.74 ! frystyk 517: if (CORE_TRACE) HTTrace("Net Object.. NO CALL BACK FUNCTION!\n");
2.49 frystyk 518: HT_FREE(me);
2.23 frystyk 519: return NO;
520: }
2.74 ! frystyk 521:
! 522: /* Increase the number of retrys for this download */
! 523: HTRequest_addRetry(request);
2.23 frystyk 524:
525: /*
526: ** Check if we can start the request, else put it into pending queue
527: ** If so then call the call back function associated with the anchor.
528: ** We use the INVSOC as we don't have a valid socket yet!
529: */
2.74 ! frystyk 530: if (CORE_TRACE)
! 531: HTTrace("Net Object.. starting request %p (retry=%d) with net object %p\n",
! 532: request, HTRequest_retrys(request), me);
! 533: (*(me->cbf))(me->sockfd, request, FD_NONE);
2.36 frystyk 534: return YES;
535: }
536:
2.23 frystyk 537: /* delete_object
538: ** -------------
539: ** Deletes an HTNet object
2.40 frystyk 540: ** Return YES if OK, else NO
2.15 frystyk 541: */
2.23 frystyk 542: PRIVATE BOOL delete_object (HTNet *net, int status)
2.15 frystyk 543: {
2.74 ! frystyk 544: if (CORE_TRACE) HTTrace("Net Object.. Remove object %p\n", net);
2.23 frystyk 545: if (net) {
546:
547: /* Close socket */
2.62 eric 548: if (net->channel) {
2.64 eric 549: HTEvent_unregister(net->sockfd, (SockOps) FD_ALL);
2.74 ! frystyk 550: if (HTHost_isPersistent(net->host)) {
2.59 frystyk 551: if (CORE_TRACE)
2.74 ! frystyk 552: HTTrace("Net Object.. keeping socket %d\n", net->sockfd);
2.70 frystyk 553: HTChannel_delete(net->channel, status);
2.24 frystyk 554: } else {
2.59 frystyk 555: if (CORE_TRACE)
2.74 ! frystyk 556: HTTrace("Net Object.. closing socket %d\n", net->sockfd);
! 557:
! 558: /*
! 559: ** By lowering the semaphore we make sure that the channel
! 560: ** is gonna be deleted
! 561: */
! 562: HTChannel_downSemaphore(net->channel);
2.70 frystyk 563: HTChannel_delete(net->channel, status);
2.24 frystyk 564: }
2.63 eric 565: net->channel = NULL;
2.23 frystyk 566: }
2.74 ! frystyk 567:
! 568: /*
! 569: ** As we may have a socket available we check for whether
! 570: ** we can start any pending requests. We do this by asking for
! 571: ** pending Host objects. If none then use the current object
! 572: */
! 573: HTHost_launchPending(net->host);
! 574:
! 575: /*
! 576: ** Break the link to the request and free the Net object
! 577: */
! 578: HTRequest_setNet(net->request, NULL);
2.49 frystyk 579: HT_FREE(net);
2.23 frystyk 580: return status ? NO : YES;
581: }
582: return NO;
583: }
584:
2.74 ! frystyk 585: /*
! 586: ** Clears the contents of the Net object so that we can use it again.
! 587: */
! 588: PUBLIC BOOL HTNet_clear (HTNet * net)
! 589: {
! 590: if (net) {
! 591: net->sockfd = INVSOC;
! 592: net->channel = NULL;
! 593: net->input = NULL;
! 594: net->bytes_read = 0;
! 595: net->bytes_written = 0;
! 596: net->tcpstate = TCP_CHANNEL;
! 597: return YES;
! 598: }
! 599: return NO;
! 600: }
! 601:
2.23 frystyk 602: /* HTNet_delete
603: ** ------------
604: ** Deletes the HTNet object from the list of active requests and calls
605: ** any registered call back functions IF not the status is HT_IGNORE.
606: ** This is used if we have internal requests that the app doesn't know
607: ** about. We also see if we have pending requests that can be started
608: ** up now when we have a socket free.
609: ** The callback functions are called in the reverse order of which they
610: ** were registered (last one first)
2.40 frystyk 611: ** Return YES if OK, else NO
2.23 frystyk 612: */
613: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
614: {
2.58 hallam 615: if (CORE_TRACE)
2.74 ! frystyk 616: HTTrace("Net Object.. Delete %p and call AFTER filters\n", net);
! 617: if (net) {
! 618: HTRequest * request = net->request;
2.23 frystyk 619:
2.25 frystyk 620: /*
2.74 ! frystyk 621: ** If we have a premature close then recover the request. Otherwise
! 622: ** break the link to the Host object and continue deleting the net
! 623: ** object
2.25 frystyk 624: */
2.74 ! frystyk 625: if (net->host) {
! 626: if (status == HT_RECOVER_PIPE) {
! 627: if (CORE_TRACE) HTTrace("Net Object.. Recovering %p\n", net);
! 628: HTChannel_setSemaphore(net->channel, 0);
! 629: HTHost_clearChannel(net->host, HT_INTERRUPTED);
! 630: HTHost_setMode(net->host, HT_TP_SINGLE);
! 631: HTNet_clear(net);
2.58 hallam 632: if (CORE_TRACE)
2.74 ! frystyk 633: HTTrace("Net Object.. Restarting request %p (retry=%d) with net object %p\n",
! 634: request, HTRequest_retrys(request), net);
! 635: HTHost_launchPending(net->host);
! 636: return YES;
! 637: } else
! 638: HTHost_deleteNet(net->host, net);
! 639: }
! 640:
! 641: /* Remove object from the table of Net Objects */
! 642: if (NetTable) {
! 643: HTList * list = NetTable[net->hash];
! 644: if (list) {
! 645: HTList_removeObject(list, (void *) net);
! 646: delete_object(net, status);
! 647: HTNetCount--;
2.23 frystyk 648: }
649: }
2.74 ! frystyk 650:
! 651: /* Call AFTER filters */
! 652: HTNet_callAfter(request, status);
! 653: return YES;
2.23 frystyk 654: }
655: return NO;
656: }
657:
658: /* HTNet_deleteAll
659: ** ---------------
660: ** Deletes all HTNet object that might either be active or pending
2.74 ! frystyk 661: ** We DO NOT call the AFTER filters - A crude way of saying goodbye!
2.23 frystyk 662: */
663: PUBLIC BOOL HTNet_deleteAll (void)
664: {
2.58 hallam 665: if (CORE_TRACE)
2.74 ! frystyk 666: HTTrace("Net Object.. Remove all Net objects, NO filters\n");
! 667: if (NetTable) {
! 668: HTList * cur = NULL;
! 669: HTNet * pres = NULL;
! 670: int cnt;
! 671: for (cnt=0; cnt<HASH_SIZE; cnt++) {
! 672: if ((cur = NetTable[cnt])) {
! 673: while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)
! 674: delete_object(pres, HT_INTERRUPTED);
! 675: }
! 676: HTList_delete(NetTable[cnt]);
2.25 frystyk 677: }
2.74 ! frystyk 678: HT_FREE(NetTable);
! 679: HTNetCount = 0;
! 680: return YES;
2.25 frystyk 681: }
682: return NO;
683: }
684:
2.23 frystyk 685: /* HTNet_kill
686: ** ----------
687: ** Kill the request by calling the call back function with a request for
688: ** closing the connection. Does not remove the object. This is done by
689: ** HTNet_delete() function which is called by the load routine.
690: ** Returns OK if success, NO on error
691: */
2.74 ! frystyk 692: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23 frystyk 693: {
2.74 ! frystyk 694: if (net && net->cbf) {
! 695: if (CORE_TRACE) HTTrace("Net Object.. Killing %p\n", net);
! 696: (*(net->cbf))(net->sockfd, net->request, FD_CLOSE);
! 697: return YES;
2.23 frystyk 698: }
2.74 ! frystyk 699: if (CORE_TRACE) HTTrace("Net Object.. No object to kill\n", net);
2.23 frystyk 700: return NO;
701: }
702:
703: /* HTNet_killAll
704: ** -------------
2.74 ! frystyk 705: ** Kills all registered net objects by calling the call
2.23 frystyk 706: ** back function with a request for closing the connection. We do not
707: ** remove the HTNet object as it is done by HTNet_delete().
708: ** Returns OK if success, NO on error
709: */
710: PUBLIC BOOL HTNet_killAll (void)
711: {
2.74 ! frystyk 712: if (CORE_TRACE) HTTrace("Net Object.. Kill ALL Net objects!!!\n");
! 713: if (NetTable) {
! 714: HTList * cur = NULL;
! 715: HTNet * pres = NULL;
! 716: int cnt;
! 717: for (cnt=0; cnt<HASH_SIZE; cnt++) {
! 718: if ((cur = NetTable[cnt])) {
! 719: while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)
! 720: HTNet_kill(pres);
! 721: }
2.25 frystyk 722: }
2.74 ! frystyk 723: return YES;
2.25 frystyk 724: }
2.74 ! frystyk 725: if (CORE_TRACE) HTTrace("Net Object.. No objects to kill\n");
! 726: return NO;
2.23 frystyk 727: }
2.38 frystyk 728:
729: /* ------------------------------------------------------------------------- */
2.59 frystyk 730: /* Connection Specifics */
731: /* ------------------------------------------------------------------------- */
732:
2.74 ! frystyk 733: /* HTNet_priority
! 734: ** --------------
! 735: ** Get the current priority of the Net object
! 736: */
! 737: PUBLIC HTPriority HTNet_priority (HTNet * net)
! 738: {
! 739: return (net ? net->priority : HT_PRIORITY_INV);
! 740: }
! 741:
! 742: /* HTNet_setPriority
! 743: ** -----------------
! 744: ** Set the current priority of the Net object
! 745: ** This will change the priority next time the thread is blocked
! 746: */
! 747: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
! 748: {
! 749: if (net) {
! 750: net->priority = priority;
! 751: return YES;
! 752: }
! 753: return NO;
! 754: }
! 755:
2.59 frystyk 756: /* HTNet_Persistent
757: ** ----------------
758: ** Check whether the net object handles persistent connections
759: ** If we have a DNS entry then check that as well.
760: */
761: PUBLIC BOOL HTNet_persistent (HTNet * net)
762: {
763: return (net && HTHost_isPersistent(net->host));
764: }
765:
766: /* HTNet_persistent
767: ** ----------------
768: ** Set the net object to handle persistent connections
769: ** If we also have a DNS entry then update that as well
770: */
2.74 ! frystyk 771: PUBLIC BOOL HTNet_setPersistent (HTNet * net,
! 772: BOOL persistent,
! 773: HTTransportMode mode)
2.59 frystyk 774: {
775: if (net) {
2.74 ! frystyk 776: BOOL result; /* Bill Rizzi */
2.59 frystyk 777: if (persistent)
2.74 ! frystyk 778: result = HTHost_setChannel(net->host, net->channel, mode);
2.59 frystyk 779: else
2.74 ! frystyk 780: result = HTHost_clearChannel(net->host, HT_OK);
! 781: if (CORE_TRACE)
! 782: HTTrace("Net Object.. Persistent connection set %s %s\n",
! 783: persistent ? "ON" : "OFF",
! 784: result ? "succeeded" : "failed");
2.59 frystyk 785: }
786: return NO;
787: }
788:
2.66 frystyk 789: /*
790: ** Context pointer to be used in context call back function
791: */
792: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
793: {
794: if (net) {
795: net->context = context;
796: return YES;
797: }
798: return NO;
799: }
800:
801: PUBLIC void * HTNet_context (HTNet * net)
802: {
803: return net ? net->context : NULL;
804: }
2.38 frystyk 805:
806: /*
2.60 frystyk 807: ** Get and set the socket number
808: */
809: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
810: {
811: if (net) {
812: net->sockfd = sockfd;
813: return YES;
814: }
815: return NO;
816: }
817:
818: PUBLIC SOCKET HTNet_socket (HTNet * net)
819: {
820: return (net ? net->sockfd : INVSOC);
2.69 frystyk 821: }
822:
823: /*
824: ** Get and set the HTRequest object
825: */
826: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
827: {
828: if (net && request) {
829: net->request = request;
830: return YES;
831: }
832: return NO;
833: }
834:
835: PUBLIC HTRequest * HTNet_request (HTNet * net)
836: {
837: return (net ? net->request : NULL);
2.60 frystyk 838: }
839:
840: /*
2.59 frystyk 841: ** Get and set the HTTransport object
2.38 frystyk 842: */
2.59 frystyk 843: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
2.38 frystyk 844: {
2.59 frystyk 845: if (net && tp) {
846: net->transport = tp;
2.38 frystyk 847: return YES;
848: }
849: return NO;
850: }
851:
2.59 frystyk 852: PUBLIC HTTransport * HTNet_transport (HTNet * net)
2.38 frystyk 853: {
2.59 frystyk 854: return (net ? net->transport : NULL);
2.38 frystyk 855: }
856:
2.55 frystyk 857: /*
2.59 frystyk 858: ** Get and set the HTChannel object
2.55 frystyk 859: */
2.59 frystyk 860: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55 frystyk 861: {
2.59 frystyk 862: if (net && channel) {
863: net->channel = channel;
2.55 frystyk 864: return YES;
865: }
866: return NO;
867: }
868:
2.59 frystyk 869: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55 frystyk 870: {
2.59 frystyk 871: return (net ? net->channel : NULL);
872: }
873:
874: /*
875: ** Get and set the HTHost object
876: */
877: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
878: {
879: if (net && host) {
880: net->host = host;
881: return YES;
882: }
883: return NO;
884: }
885:
886: PUBLIC HTHost * HTNet_host (HTNet * net)
887: {
888: return (net ? net->host : NULL);
889: }
890:
891: /*
892: ** Get and set the HTdns object
893: */
894: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
895: {
896: if (net && dns) {
897: net->dns = dns;
898: return YES;
899: }
900: return NO;
901: }
902:
903: PUBLIC HTdns * HTNet_dns (HTNet * net)
904: {
905: return (net ? net->dns : NULL);
906: }
907:
2.72 frystyk 908: PUBLIC int HTNet_home (HTNet * net)
909: {
910: return (net ? net->home : 0);
911: }
2.59 frystyk 912:
913: /*
914: ** Create the input stream and bind it to the channel
915: ** Please read the description in the HTIOStream module for the parameters
916: */
917: PUBLIC HTInputStream * HTNet_getInput (HTNet * net, HTStream * target,
918: void * param, int mode)
919: {
920: if (net && net->channel && net->transport) {
921: HTTransport * tp = net->transport;
922: HTChannel * ch = net->channel;
923: net->input = (*tp->input_new)(net, ch, target, param, mode);
2.74 ! frystyk 924: HTChannel_setInput(ch, net->input);
2.59 frystyk 925: return net->input;
926: }
2.74 ! frystyk 927: if (CORE_TRACE) HTTrace("Net Object.. Can't create input stream\n");
2.59 frystyk 928: return NULL;
929: }
930:
931: /*
932: ** Create the output stream and bind it to the channel
933: ** Please read the description in the HTIOStream module on the parameters
934: */
935: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * net, void * param, int mode)
936: {
937: if (net && net->request && net->channel && net->transport) {
938: HTTransport * tp = net->transport;
939: HTChannel * ch = net->channel;
940: HTOutputStream * output = (*tp->output_new)(net, ch, param, mode);
2.74 ! frystyk 941: HTChannel_setOutput(ch, output);
2.59 frystyk 942: return output;
943: }
2.74 ! frystyk 944: if (CORE_TRACE) HTTrace("Net Object.. Can't create output stream\n");
2.59 frystyk 945: return NULL;
2.55 frystyk 946: }
Webmaster