Annotation of libwww/Library/src/HTNet.c, revision 2.77
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.77 ! frystyk 6: ** @(#) $Id: HTNet.c,v 2.76 1996/08/24 18:10:09 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: {
2.77 ! frystyk 250: return HTNetCall_delete(HTAfter, 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;
2.75 frystyk 358: int hash;
2.74 frystyk 359: if ((me = create_object()) == NULL) return NULL;
2.75 frystyk 360: hash = me->hash;
2.74 frystyk 361: if (CORE_TRACE) HTTrace("Net Object.. Duplicated %p\n", src);
362: memcpy((void *) me, src, sizeof(HTNet));
2.75 frystyk 363: me->hash = hash; /* Carry over hash entry */
2.74 frystyk 364: return me;
365: }
366: return NULL;
2.27 frystyk 367: }
368:
2.74 frystyk 369: /*
370: ** Start a Net obejct by calling the protocol module.
2.30 frystyk 371: */
2.74 frystyk 372: PUBLIC BOOL HTNet_start (HTNet * net)
2.30 frystyk 373: {
2.74 frystyk 374: if (net && net->cbf && net->request) {
375: if (CORE_TRACE) HTTrace("Net Object.. Launching %p\n", net);
376: HTEvent_unregister(net->sockfd, (SockOps) FD_ALL);
377: (*(net->cbf))(net->sockfd, net->request, FD_NONE);
2.30 frystyk 378: return YES;
379: }
380: return NO;
381: }
382:
2.37 frystyk 383: /* HTNet_new
384: ** ---------
385: ** This function creates a new HTNet object and assigns the socket number
386: ** to it. This is intended to be used when you are going to listen on a
387: ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
388: ** call any of the callback functions.
389: ** Returns new object or NULL on error
390: */
2.69 frystyk 391: PUBLIC HTNet * HTNet_new (SOCKET sockfd, HTRequest * request)
2.37 frystyk 392: {
2.69 frystyk 393: if (sockfd != INVSOC) {
394: HTNet * me;
395: if ((me = create_object()) == NULL) return NULL;
396: me->preemptive = HTRequest_preemptive(request);
397: me->priority = HTRequest_priority(request);
398: me->sockfd = sockfd;
399: me->request = request;
400: HTRequest_setNet(request, me);
401: return me;
402: }
2.74 frystyk 403: if (CORE_TRACE) HTTrace("Net Object.. Can't create empty Net object!\n");
2.69 frystyk 404: return NULL;
2.37 frystyk 405: }
406:
2.67 frystyk 407: /* HTNet_newServer
408: ** ---------------
409: ** Create a new HTNet object as a new request to be handled. If we have
2.74 frystyk 410: ** more than MaxActive connections already then return NO.
2.67 frystyk 411: ** Returns YES if OK, else NO
2.37 frystyk 412: */
2.69 frystyk 413: PUBLIC BOOL HTNet_newServer (HTRequest * request, HTNet * net, char * access)
2.37 frystyk 414: {
415: HTProtocol * protocol;
2.67 frystyk 416: HTTransport * tp = NULL; /* added JTD:5/28/96 */
2.37 frystyk 417: if (!request) return NO;
418:
419: /* Find a protocol object for this access scheme */
2.46 frystyk 420: protocol = HTProtocol_find(request, access);
2.67 frystyk 421:
422: /* added - JTD:5/28/96 */
423: /* Find a transport object for this protocol */
424: tp = HTTransport_find(request, HTProtocol_transport(protocol));
425: if (tp == NULL) {
2.74 frystyk 426: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT OBJECT\n");
2.67 frystyk 427: return NO;
428: }
429: /* end of additions - JTD:5/28/96 */
430:
2.69 frystyk 431: /* Fill out the net object and bind it to the request object */
2.74 frystyk 432: net->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.69 frystyk 433: net->protocol = protocol;
434: net->transport = tp; /* added - JTD:5/28/96 */
435: net->priority = HTRequest_priority(request);
436: net->request = request;
437: HTRequest_setNet(request, net);
438: if (!(net->cbf = HTProtocol_server(protocol))) {
2.74 frystyk 439: if (CORE_TRACE) HTTrace("Net Object.. NO CALL BACK FUNCTION!\n");
2.67 frystyk 440: return NO;
2.37 frystyk 441: }
2.74 frystyk 442:
443: /* Increase the number of retrys for this download */
444: HTRequest_addRetry(request);
2.37 frystyk 445:
446: /* Start the server request */
2.58 hallam 447: if (CORE_TRACE)
2.74 frystyk 448: HTTrace("Net Object.. starting SERVER request %p with net object %p\n", request, net);
2.69 frystyk 449: (*(net->cbf))(net->sockfd, request, FD_NONE);
2.37 frystyk 450: return YES;
451: }
2.36 frystyk 452:
2.30 frystyk 453: /* HTNet_new
454: ** ---------
2.23 frystyk 455: ** Create a new HTNet object as a new request to be handled. If we have
2.74 frystyk 456: ** more than MaxActive connections already then put this into the
2.23 frystyk 457: ** pending queue, else start the request by calling the call back
458: ** function registered with this access method.
459: ** Returns YES if OK, else NO
460: */
2.37 frystyk 461: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23 frystyk 462: {
2.74 frystyk 463: HTParentAnchor * anchor = HTRequest_anchor(request);
2.59 frystyk 464: HTNet * me = NULL;
465: HTProtocol * protocol = NULL;
466: HTTransport * tp = NULL;
2.37 frystyk 467: char * physical = NULL;
2.74 frystyk 468: int status;
2.27 frystyk 469: if (!request) return NO;
2.33 frystyk 470: /*
471: ** First we do all the "BEFORE" callbacks in order to see if we are to
472: ** continue with this request or not. If we receive a callback status
473: ** that is NOT HT_OK then jump directly to the after callbacks and return
474: */
2.58 hallam 475: if ((status = HTNet_callBefore(request, HT_OK)) != HT_OK) {
476: HTNet_callAfter(request, status);
2.33 frystyk 477: return YES;
478: }
479:
2.36 frystyk 480: /*
481: ** If no translation was provided by the application then use the anchor
482: ** address directly
483: */
2.74 frystyk 484: if (!(physical = HTAnchor_physical(anchor))) {
485: char * addr = HTAnchor_address((HTAnchor *) anchor);
486: if (CORE_TRACE) HTTrace("Net Object.. Using default address\n");
487: HTAnchor_setPhysical(anchor, addr);
488: physical = HTAnchor_physical(anchor);
2.49 frystyk 489: HT_FREE(addr);
2.33 frystyk 490: }
491:
2.37 frystyk 492: /* Find a protocol object for this access scheme */
493: {
494: char * access = HTParse(physical, "", PARSE_ACCESS);
495: if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.74 frystyk 496: if (CORE_TRACE) HTTrace("Net Object.. NO PROTOCOL OBJECT\n");
2.49 frystyk 497: HT_FREE(access);
2.37 frystyk 498: return NO;
499: }
2.49 frystyk 500: HT_FREE(access);
2.37 frystyk 501: }
2.59 frystyk 502:
503: /* Find a transport object for this protocol */
504: tp = HTTransport_find(request, HTProtocol_transport(protocol));
505: if (tp == NULL) {
2.74 frystyk 506: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT OBJECT\n");
2.59 frystyk 507: return NO;
508: }
509:
2.23 frystyk 510: /* Create new net object and bind it to the request object */
2.69 frystyk 511: if ((me = create_object()) == NULL) return NO;
2.74 frystyk 512: me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.69 frystyk 513: me->priority = HTRequest_priority(request);
2.23 frystyk 514: me->sockfd = INVSOC;
2.59 frystyk 515: me->protocol = protocol;
516: me->transport = tp;
2.69 frystyk 517: me->request = request;
518: HTRequest_setNet(request, me);
2.37 frystyk 519: if (!(me->cbf = HTProtocol_client(protocol))) {
2.74 frystyk 520: if (CORE_TRACE) HTTrace("Net Object.. NO CALL BACK FUNCTION!\n");
2.49 frystyk 521: HT_FREE(me);
2.23 frystyk 522: return NO;
523: }
2.74 frystyk 524:
525: /* Increase the number of retrys for this download */
526: HTRequest_addRetry(request);
2.23 frystyk 527:
528: /*
529: ** Check if we can start the request, else put it into pending queue
530: ** If so then call the call back function associated with the anchor.
531: ** We use the INVSOC as we don't have a valid socket yet!
532: */
2.74 frystyk 533: if (CORE_TRACE)
534: HTTrace("Net Object.. starting request %p (retry=%d) with net object %p\n",
535: request, HTRequest_retrys(request), me);
536: (*(me->cbf))(me->sockfd, request, FD_NONE);
2.36 frystyk 537: return YES;
538: }
539:
2.23 frystyk 540: /* delete_object
541: ** -------------
542: ** Deletes an HTNet object
2.40 frystyk 543: ** Return YES if OK, else NO
2.15 frystyk 544: */
2.23 frystyk 545: PRIVATE BOOL delete_object (HTNet *net, int status)
2.15 frystyk 546: {
2.74 frystyk 547: if (CORE_TRACE) HTTrace("Net Object.. Remove object %p\n", net);
2.23 frystyk 548: if (net) {
549:
550: /* Close socket */
2.62 eric 551: if (net->channel) {
2.64 eric 552: HTEvent_unregister(net->sockfd, (SockOps) FD_ALL);
2.74 frystyk 553: if (HTHost_isPersistent(net->host)) {
2.59 frystyk 554: if (CORE_TRACE)
2.74 frystyk 555: HTTrace("Net Object.. keeping socket %d\n", net->sockfd);
2.70 frystyk 556: HTChannel_delete(net->channel, status);
2.24 frystyk 557: } else {
2.59 frystyk 558: if (CORE_TRACE)
2.74 frystyk 559: HTTrace("Net Object.. closing socket %d\n", net->sockfd);
560:
561: /*
562: ** By lowering the semaphore we make sure that the channel
563: ** is gonna be deleted
564: */
565: HTChannel_downSemaphore(net->channel);
2.70 frystyk 566: HTChannel_delete(net->channel, status);
2.24 frystyk 567: }
2.63 eric 568: net->channel = NULL;
2.23 frystyk 569: }
2.74 frystyk 570:
571: /*
572: ** As we may have a socket available we check for whether
573: ** we can start any pending requests. We do this by asking for
574: ** pending Host objects. If none then use the current object
575: */
576: HTHost_launchPending(net->host);
577:
578: /*
579: ** Break the link to the request and free the Net object
580: */
581: HTRequest_setNet(net->request, NULL);
2.49 frystyk 582: HT_FREE(net);
2.23 frystyk 583: return status ? NO : YES;
584: }
585: return NO;
586: }
587:
2.74 frystyk 588: /*
589: ** Clears the contents of the Net object so that we can use it again.
590: */
591: PUBLIC BOOL HTNet_clear (HTNet * net)
592: {
593: if (net) {
594: net->sockfd = INVSOC;
595: net->channel = NULL;
596: net->input = NULL;
597: net->bytes_read = 0;
598: net->bytes_written = 0;
599: net->tcpstate = TCP_CHANNEL;
600: return YES;
601: }
602: return NO;
603: }
604:
2.23 frystyk 605: /* HTNet_delete
606: ** ------------
607: ** Deletes the HTNet object from the list of active requests and calls
608: ** any registered call back functions IF not the status is HT_IGNORE.
609: ** This is used if we have internal requests that the app doesn't know
610: ** about. We also see if we have pending requests that can be started
611: ** up now when we have a socket free.
612: ** The callback functions are called in the reverse order of which they
613: ** were registered (last one first)
2.40 frystyk 614: ** Return YES if OK, else NO
2.23 frystyk 615: */
616: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
617: {
2.58 hallam 618: if (CORE_TRACE)
2.74 frystyk 619: HTTrace("Net Object.. Delete %p and call AFTER filters\n", net);
620: if (net) {
621: HTRequest * request = net->request;
2.23 frystyk 622:
2.25 frystyk 623: /*
2.74 frystyk 624: ** If we have a premature close then recover the request. Otherwise
625: ** break the link to the Host object and continue deleting the net
626: ** object
2.25 frystyk 627: */
2.74 frystyk 628: if (net->host) {
629: if (status == HT_RECOVER_PIPE) {
630: if (CORE_TRACE) HTTrace("Net Object.. Recovering %p\n", net);
631: HTChannel_setSemaphore(net->channel, 0);
632: HTHost_clearChannel(net->host, HT_INTERRUPTED);
633: HTHost_setMode(net->host, HT_TP_SINGLE);
634: HTNet_clear(net);
2.58 hallam 635: if (CORE_TRACE)
2.74 frystyk 636: HTTrace("Net Object.. Restarting request %p (retry=%d) with net object %p\n",
637: request, HTRequest_retrys(request), net);
638: HTHost_launchPending(net->host);
639: return YES;
640: } else
641: HTHost_deleteNet(net->host, net);
642: }
643:
644: /* Remove object from the table of Net Objects */
645: if (NetTable) {
646: HTList * list = NetTable[net->hash];
647: if (list) {
648: HTList_removeObject(list, (void *) net);
649: delete_object(net, status);
650: HTNetCount--;
2.23 frystyk 651: }
652: }
2.74 frystyk 653:
654: /* Call AFTER filters */
655: HTNet_callAfter(request, status);
656: return YES;
2.23 frystyk 657: }
658: return NO;
659: }
660:
661: /* HTNet_deleteAll
662: ** ---------------
663: ** Deletes all HTNet object that might either be active or pending
2.74 frystyk 664: ** We DO NOT call the AFTER filters - A crude way of saying goodbye!
2.23 frystyk 665: */
666: PUBLIC BOOL HTNet_deleteAll (void)
667: {
2.58 hallam 668: if (CORE_TRACE)
2.74 frystyk 669: HTTrace("Net Object.. Remove all Net objects, NO filters\n");
670: if (NetTable) {
671: HTList * cur = NULL;
672: HTNet * pres = NULL;
673: int cnt;
674: for (cnt=0; cnt<HASH_SIZE; cnt++) {
675: if ((cur = NetTable[cnt])) {
676: while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)
677: delete_object(pres, HT_INTERRUPTED);
678: }
679: HTList_delete(NetTable[cnt]);
2.25 frystyk 680: }
2.74 frystyk 681: HT_FREE(NetTable);
682: HTNetCount = 0;
683: return YES;
2.25 frystyk 684: }
685: return NO;
686: }
687:
2.23 frystyk 688: /* HTNet_kill
689: ** ----------
690: ** Kill the request by calling the call back function with a request for
691: ** closing the connection. Does not remove the object. This is done by
692: ** HTNet_delete() function which is called by the load routine.
693: ** Returns OK if success, NO on error
694: */
2.74 frystyk 695: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23 frystyk 696: {
2.74 frystyk 697: if (net && net->cbf) {
698: if (CORE_TRACE) HTTrace("Net Object.. Killing %p\n", net);
699: (*(net->cbf))(net->sockfd, net->request, FD_CLOSE);
700: return YES;
2.23 frystyk 701: }
2.74 frystyk 702: if (CORE_TRACE) HTTrace("Net Object.. No object to kill\n", net);
2.23 frystyk 703: return NO;
704: }
705:
706: /* HTNet_killAll
707: ** -------------
2.74 frystyk 708: ** Kills all registered net objects by calling the call
2.23 frystyk 709: ** back function with a request for closing the connection. We do not
710: ** remove the HTNet object as it is done by HTNet_delete().
711: ** Returns OK if success, NO on error
712: */
713: PUBLIC BOOL HTNet_killAll (void)
714: {
2.74 frystyk 715: if (CORE_TRACE) HTTrace("Net Object.. Kill ALL Net objects!!!\n");
716: if (NetTable) {
717: HTList * cur = NULL;
718: HTNet * pres = NULL;
719: int cnt;
720: for (cnt=0; cnt<HASH_SIZE; cnt++) {
721: if ((cur = NetTable[cnt])) {
2.75 frystyk 722: while ((pres = (HTNet *) HTList_lastObject(cur)) != NULL)
2.74 frystyk 723: HTNet_kill(pres);
724: }
2.25 frystyk 725: }
2.74 frystyk 726: return YES;
2.25 frystyk 727: }
2.74 frystyk 728: if (CORE_TRACE) HTTrace("Net Object.. No objects to kill\n");
729: return NO;
2.23 frystyk 730: }
2.38 frystyk 731:
732: /* ------------------------------------------------------------------------- */
2.59 frystyk 733: /* Connection Specifics */
734: /* ------------------------------------------------------------------------- */
735:
2.74 frystyk 736: /* HTNet_priority
737: ** --------------
738: ** Get the current priority of the Net object
739: */
740: PUBLIC HTPriority HTNet_priority (HTNet * net)
741: {
742: return (net ? net->priority : HT_PRIORITY_INV);
743: }
744:
745: /* HTNet_setPriority
746: ** -----------------
747: ** Set the current priority of the Net object
748: ** This will change the priority next time the thread is blocked
749: */
750: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
751: {
752: if (net) {
753: net->priority = priority;
754: return YES;
755: }
756: return NO;
757: }
758:
2.59 frystyk 759: /* HTNet_Persistent
760: ** ----------------
761: ** Check whether the net object handles persistent connections
762: ** If we have a DNS entry then check that as well.
763: */
764: PUBLIC BOOL HTNet_persistent (HTNet * net)
765: {
766: return (net && HTHost_isPersistent(net->host));
767: }
768:
769: /* HTNet_persistent
770: ** ----------------
771: ** Set the net object to handle persistent connections
772: ** If we also have a DNS entry then update that as well
773: */
2.74 frystyk 774: PUBLIC BOOL HTNet_setPersistent (HTNet * net,
775: BOOL persistent,
776: HTTransportMode mode)
2.59 frystyk 777: {
778: if (net) {
2.74 frystyk 779: BOOL result; /* Bill Rizzi */
2.59 frystyk 780: if (persistent)
2.74 frystyk 781: result = HTHost_setChannel(net->host, net->channel, mode);
2.76 frystyk 782: else {
783:
784: /*
785: ** We use the HT_IGNORE status code as we don't want to free
786: ** the stream at this point in time. The situation we want to
787: ** avoid is that we free the channel from within the stream pipe.
788: ** This will lead to an infinite look having the stream freing
789: ** itself.
790: */
791: result = HTHost_clearChannel(net->host, HT_IGNORE);
792: }
2.74 frystyk 793: if (CORE_TRACE)
794: HTTrace("Net Object.. Persistent connection set %s %s\n",
795: persistent ? "ON" : "OFF",
796: result ? "succeeded" : "failed");
2.59 frystyk 797: }
798: return NO;
799: }
800:
2.66 frystyk 801: /*
802: ** Context pointer to be used in context call back function
803: */
804: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
805: {
806: if (net) {
807: net->context = context;
808: return YES;
809: }
810: return NO;
811: }
812:
813: PUBLIC void * HTNet_context (HTNet * net)
814: {
815: return net ? net->context : NULL;
816: }
2.38 frystyk 817:
818: /*
2.60 frystyk 819: ** Get and set the socket number
820: */
821: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
822: {
823: if (net) {
824: net->sockfd = sockfd;
825: return YES;
826: }
827: return NO;
828: }
829:
830: PUBLIC SOCKET HTNet_socket (HTNet * net)
831: {
832: return (net ? net->sockfd : INVSOC);
2.69 frystyk 833: }
834:
835: /*
836: ** Get and set the HTRequest object
837: */
838: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
839: {
840: if (net && request) {
841: net->request = request;
842: return YES;
843: }
844: return NO;
845: }
846:
847: PUBLIC HTRequest * HTNet_request (HTNet * net)
848: {
849: return (net ? net->request : NULL);
2.60 frystyk 850: }
851:
852: /*
2.59 frystyk 853: ** Get and set the HTTransport object
2.38 frystyk 854: */
2.59 frystyk 855: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
2.38 frystyk 856: {
2.59 frystyk 857: if (net && tp) {
858: net->transport = tp;
2.38 frystyk 859: return YES;
860: }
861: return NO;
862: }
863:
2.59 frystyk 864: PUBLIC HTTransport * HTNet_transport (HTNet * net)
2.38 frystyk 865: {
2.59 frystyk 866: return (net ? net->transport : NULL);
2.38 frystyk 867: }
868:
2.55 frystyk 869: /*
2.59 frystyk 870: ** Get and set the HTChannel object
2.55 frystyk 871: */
2.59 frystyk 872: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55 frystyk 873: {
2.59 frystyk 874: if (net && channel) {
875: net->channel = channel;
2.55 frystyk 876: return YES;
877: }
878: return NO;
879: }
880:
2.59 frystyk 881: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55 frystyk 882: {
2.59 frystyk 883: return (net ? net->channel : NULL);
884: }
885:
886: /*
887: ** Get and set the HTHost object
888: */
889: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
890: {
891: if (net && host) {
892: net->host = host;
893: return YES;
894: }
895: return NO;
896: }
897:
898: PUBLIC HTHost * HTNet_host (HTNet * net)
899: {
900: return (net ? net->host : NULL);
901: }
902:
903: /*
904: ** Get and set the HTdns object
905: */
906: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
907: {
908: if (net && dns) {
909: net->dns = dns;
910: return YES;
911: }
912: return NO;
913: }
914:
915: PUBLIC HTdns * HTNet_dns (HTNet * net)
916: {
917: return (net ? net->dns : NULL);
918: }
919:
2.72 frystyk 920: PUBLIC int HTNet_home (HTNet * net)
921: {
922: return (net ? net->home : 0);
923: }
2.59 frystyk 924:
925: /*
926: ** Create the input stream and bind it to the channel
927: ** Please read the description in the HTIOStream module for the parameters
928: */
929: PUBLIC HTInputStream * HTNet_getInput (HTNet * net, HTStream * target,
930: void * param, int mode)
931: {
932: if (net && net->channel && net->transport) {
933: HTTransport * tp = net->transport;
934: HTChannel * ch = net->channel;
935: net->input = (*tp->input_new)(net, ch, target, param, mode);
2.74 frystyk 936: HTChannel_setInput(ch, net->input);
2.59 frystyk 937: return net->input;
938: }
2.74 frystyk 939: if (CORE_TRACE) HTTrace("Net Object.. Can't create input stream\n");
2.59 frystyk 940: return NULL;
941: }
942:
943: /*
944: ** Create the output stream and bind it to the channel
945: ** Please read the description in the HTIOStream module on the parameters
946: */
947: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * net, void * param, int mode)
948: {
949: if (net && net->request && net->channel && net->transport) {
950: HTTransport * tp = net->transport;
951: HTChannel * ch = net->channel;
952: HTOutputStream * output = (*tp->output_new)(net, ch, param, mode);
2.74 frystyk 953: HTChannel_setOutput(ch, output);
2.59 frystyk 954: return output;
955: }
2.74 frystyk 956: if (CORE_TRACE) HTTrace("Net Object.. Can't create output stream\n");
2.59 frystyk 957: return NULL;
2.55 frystyk 958: }
Webmaster