Annotation of libwww/Library/src/HTNet.c, revision 2.78
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.78 ! frystyk 6: ** @(#) $Id: HTNet.c,v 2.77 1996/09/08 22:08:36 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);
2.78 ! frystyk 638: #if 0
2.74 frystyk 639: HTHost_launchPending(net->host);
640: return YES;
2.78 ! frystyk 641: #else
! 642: return HTNet_start(net);
! 643: #endif
2.74 frystyk 644: } else
645: HTHost_deleteNet(net->host, net);
646: }
647:
648: /* Remove object from the table of Net Objects */
649: if (NetTable) {
650: HTList * list = NetTable[net->hash];
651: if (list) {
652: HTList_removeObject(list, (void *) net);
653: delete_object(net, status);
654: HTNetCount--;
2.23 frystyk 655: }
656: }
2.74 frystyk 657:
658: /* Call AFTER filters */
659: HTNet_callAfter(request, status);
660: return YES;
2.23 frystyk 661: }
662: return NO;
663: }
664:
665: /* HTNet_deleteAll
666: ** ---------------
667: ** Deletes all HTNet object that might either be active or pending
2.74 frystyk 668: ** We DO NOT call the AFTER filters - A crude way of saying goodbye!
2.23 frystyk 669: */
670: PUBLIC BOOL HTNet_deleteAll (void)
671: {
2.58 hallam 672: if (CORE_TRACE)
2.74 frystyk 673: HTTrace("Net Object.. Remove all Net objects, NO filters\n");
674: if (NetTable) {
675: HTList * cur = NULL;
676: HTNet * pres = NULL;
677: int cnt;
678: for (cnt=0; cnt<HASH_SIZE; cnt++) {
679: if ((cur = NetTable[cnt])) {
680: while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)
681: delete_object(pres, HT_INTERRUPTED);
682: }
683: HTList_delete(NetTable[cnt]);
2.25 frystyk 684: }
2.74 frystyk 685: HT_FREE(NetTable);
686: HTNetCount = 0;
687: return YES;
2.25 frystyk 688: }
689: return NO;
690: }
691:
2.23 frystyk 692: /* HTNet_kill
693: ** ----------
694: ** Kill the request by calling the call back function with a request for
695: ** closing the connection. Does not remove the object. This is done by
696: ** HTNet_delete() function which is called by the load routine.
697: ** Returns OK if success, NO on error
698: */
2.74 frystyk 699: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23 frystyk 700: {
2.74 frystyk 701: if (net && net->cbf) {
702: if (CORE_TRACE) HTTrace("Net Object.. Killing %p\n", net);
703: (*(net->cbf))(net->sockfd, net->request, FD_CLOSE);
704: return YES;
2.23 frystyk 705: }
2.74 frystyk 706: if (CORE_TRACE) HTTrace("Net Object.. No object to kill\n", net);
2.23 frystyk 707: return NO;
708: }
709:
710: /* HTNet_killAll
711: ** -------------
2.74 frystyk 712: ** Kills all registered net objects by calling the call
2.23 frystyk 713: ** back function with a request for closing the connection. We do not
714: ** remove the HTNet object as it is done by HTNet_delete().
715: ** Returns OK if success, NO on error
716: */
717: PUBLIC BOOL HTNet_killAll (void)
718: {
2.74 frystyk 719: if (CORE_TRACE) HTTrace("Net Object.. Kill ALL Net objects!!!\n");
720: if (NetTable) {
721: HTList * cur = NULL;
722: HTNet * pres = NULL;
723: int cnt;
724: for (cnt=0; cnt<HASH_SIZE; cnt++) {
725: if ((cur = NetTable[cnt])) {
2.75 frystyk 726: while ((pres = (HTNet *) HTList_lastObject(cur)) != NULL)
2.74 frystyk 727: HTNet_kill(pres);
728: }
2.25 frystyk 729: }
2.74 frystyk 730: return YES;
2.25 frystyk 731: }
2.74 frystyk 732: if (CORE_TRACE) HTTrace("Net Object.. No objects to kill\n");
733: return NO;
2.23 frystyk 734: }
2.38 frystyk 735:
736: /* ------------------------------------------------------------------------- */
2.59 frystyk 737: /* Connection Specifics */
738: /* ------------------------------------------------------------------------- */
739:
2.74 frystyk 740: /* HTNet_priority
741: ** --------------
742: ** Get the current priority of the Net object
743: */
744: PUBLIC HTPriority HTNet_priority (HTNet * net)
745: {
746: return (net ? net->priority : HT_PRIORITY_INV);
747: }
748:
749: /* HTNet_setPriority
750: ** -----------------
751: ** Set the current priority of the Net object
752: ** This will change the priority next time the thread is blocked
753: */
754: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
755: {
756: if (net) {
757: net->priority = priority;
758: return YES;
759: }
760: return NO;
761: }
762:
2.59 frystyk 763: /* HTNet_Persistent
764: ** ----------------
765: ** Check whether the net object handles persistent connections
766: ** If we have a DNS entry then check that as well.
767: */
768: PUBLIC BOOL HTNet_persistent (HTNet * net)
769: {
770: return (net && HTHost_isPersistent(net->host));
771: }
772:
773: /* HTNet_persistent
774: ** ----------------
775: ** Set the net object to handle persistent connections
776: ** If we also have a DNS entry then update that as well
777: */
2.74 frystyk 778: PUBLIC BOOL HTNet_setPersistent (HTNet * net,
779: BOOL persistent,
780: HTTransportMode mode)
2.59 frystyk 781: {
782: if (net) {
2.74 frystyk 783: BOOL result; /* Bill Rizzi */
2.59 frystyk 784: if (persistent)
2.74 frystyk 785: result = HTHost_setChannel(net->host, net->channel, mode);
2.76 frystyk 786: else {
787:
788: /*
789: ** We use the HT_IGNORE status code as we don't want to free
790: ** the stream at this point in time. The situation we want to
791: ** avoid is that we free the channel from within the stream pipe.
792: ** This will lead to an infinite look having the stream freing
793: ** itself.
794: */
795: result = HTHost_clearChannel(net->host, HT_IGNORE);
796: }
2.74 frystyk 797: if (CORE_TRACE)
798: HTTrace("Net Object.. Persistent connection set %s %s\n",
799: persistent ? "ON" : "OFF",
800: result ? "succeeded" : "failed");
2.59 frystyk 801: }
802: return NO;
803: }
804:
2.66 frystyk 805: /*
806: ** Context pointer to be used in context call back function
807: */
808: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
809: {
810: if (net) {
811: net->context = context;
812: return YES;
813: }
814: return NO;
815: }
816:
817: PUBLIC void * HTNet_context (HTNet * net)
818: {
819: return net ? net->context : NULL;
820: }
2.38 frystyk 821:
822: /*
2.60 frystyk 823: ** Get and set the socket number
824: */
825: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
826: {
827: if (net) {
828: net->sockfd = sockfd;
829: return YES;
830: }
831: return NO;
832: }
833:
834: PUBLIC SOCKET HTNet_socket (HTNet * net)
835: {
836: return (net ? net->sockfd : INVSOC);
2.69 frystyk 837: }
838:
839: /*
840: ** Get and set the HTRequest object
841: */
842: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
843: {
844: if (net && request) {
845: net->request = request;
846: return YES;
847: }
848: return NO;
849: }
850:
851: PUBLIC HTRequest * HTNet_request (HTNet * net)
852: {
853: return (net ? net->request : NULL);
2.60 frystyk 854: }
855:
856: /*
2.59 frystyk 857: ** Get and set the HTTransport object
2.38 frystyk 858: */
2.59 frystyk 859: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
2.38 frystyk 860: {
2.59 frystyk 861: if (net && tp) {
862: net->transport = tp;
2.38 frystyk 863: return YES;
864: }
865: return NO;
866: }
867:
2.59 frystyk 868: PUBLIC HTTransport * HTNet_transport (HTNet * net)
2.38 frystyk 869: {
2.59 frystyk 870: return (net ? net->transport : NULL);
2.38 frystyk 871: }
872:
2.55 frystyk 873: /*
2.59 frystyk 874: ** Get and set the HTChannel object
2.55 frystyk 875: */
2.59 frystyk 876: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55 frystyk 877: {
2.59 frystyk 878: if (net && channel) {
879: net->channel = channel;
2.55 frystyk 880: return YES;
881: }
882: return NO;
883: }
884:
2.59 frystyk 885: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55 frystyk 886: {
2.59 frystyk 887: return (net ? net->channel : NULL);
888: }
889:
890: /*
891: ** Get and set the HTHost object
892: */
893: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
894: {
895: if (net && host) {
896: net->host = host;
897: return YES;
898: }
899: return NO;
900: }
901:
902: PUBLIC HTHost * HTNet_host (HTNet * net)
903: {
904: return (net ? net->host : NULL);
905: }
906:
907: /*
908: ** Get and set the HTdns object
909: */
910: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
911: {
912: if (net && dns) {
913: net->dns = dns;
914: return YES;
915: }
916: return NO;
917: }
918:
919: PUBLIC HTdns * HTNet_dns (HTNet * net)
920: {
921: return (net ? net->dns : NULL);
922: }
923:
2.72 frystyk 924: PUBLIC int HTNet_home (HTNet * net)
925: {
926: return (net ? net->home : 0);
927: }
2.59 frystyk 928:
929: /*
930: ** Create the input stream and bind it to the channel
931: ** Please read the description in the HTIOStream module for the parameters
932: */
933: PUBLIC HTInputStream * HTNet_getInput (HTNet * net, HTStream * target,
934: void * param, int mode)
935: {
936: if (net && net->channel && net->transport) {
937: HTTransport * tp = net->transport;
938: HTChannel * ch = net->channel;
939: net->input = (*tp->input_new)(net, ch, target, param, mode);
2.74 frystyk 940: HTChannel_setInput(ch, net->input);
2.59 frystyk 941: return net->input;
942: }
2.74 frystyk 943: if (CORE_TRACE) HTTrace("Net Object.. Can't create input stream\n");
2.59 frystyk 944: return NULL;
945: }
946:
947: /*
948: ** Create the output stream and bind it to the channel
949: ** Please read the description in the HTIOStream module on the parameters
950: */
951: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * net, void * param, int mode)
952: {
953: if (net && net->request && net->channel && net->transport) {
954: HTTransport * tp = net->transport;
955: HTChannel * ch = net->channel;
956: HTOutputStream * output = (*tp->output_new)(net, ch, param, mode);
2.74 frystyk 957: HTChannel_setOutput(ch, output);
2.59 frystyk 958: return output;
959: }
2.74 frystyk 960: if (CORE_TRACE) HTTrace("Net Object.. Can't create output stream\n");
2.59 frystyk 961: return NULL;
2.55 frystyk 962: }
Webmaster