Annotation of libwww/Library/src/HTNet.c, revision 2.79.2.9
2.23 frystyk 1: /* HTNet.c
2.79 frystyk 2: ** HTNet Class
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.79.2.9! eric 6: ** @(#) $Id: HTNet.c,v 2.79.2.8 1996/11/07 18:47:33 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.79.2.1 eric 31: #include "HTHstMan.h"
32: #include "HTIOStream.h"
2.24 frystyk 33: #include "HTNetMan.h" /* Implemented here */
2.1 frystyk 34:
2.23 frystyk 35: #ifndef HT_MAX_SOCKETS
36: #define HT_MAX_SOCKETS 6
37: #endif
38:
2.74 frystyk 39: #define HASH_SIZE 67
40:
2.79 frystyk 41: typedef struct _BeforeFilter {
42: HTNetBefore * before; /* Filter function */
43: char * tmplate; /* URL template for when to call filter */
44: int order; /* Relative execution order */
2.60 frystyk 45: void * param; /* Local context */
2.79 frystyk 46: } BeforeFilter;
47:
48: typedef struct _AfterFilter {
49: HTNetAfter * after; /* Filter function */
50: char * tmplate; /* URL template for when to call filter */
51: int order; /* Relative execution order */
52: void * param; /* Local context */
53: int status; /* Status of load for when to call filter */
54: } AfterFilter;
2.23 frystyk 55:
56: struct _HTStream {
2.52 frystyk 57: const HTStreamClass * isa;
2.23 frystyk 58: /* ... */
59: };
60:
2.79.2.1 eric 61: struct _HTInputStream {
62: const HTInputStreamClass * isa;
63: /* ... */
64: };
65:
2.79 frystyk 66: PRIVATE HTList * HTBefore = NULL; /* List of global BEFORE filters */
67: PRIVATE HTList * HTAfter = NULL; /* List of global AFTER filters */
2.24 frystyk 68:
2.74 frystyk 69: PRIVATE int MaxActive = HT_MAX_SOCKETS; /* Max active requests */
70: PRIVATE int Active = 0; /* Counts open sockets */
71: PRIVATE int Persistent = 0; /* Counts persistent sockets */
2.1 frystyk 72:
2.74 frystyk 73: PRIVATE HTList ** NetTable = NULL; /* List of net objects */
74: PRIVATE int HTNetCount = 0; /* Counting elements in table */
2.23 frystyk 75:
76: /* ------------------------------------------------------------------------- */
2.79 frystyk 77: /* GENERIC BEFORE and AFTER filter Management */
2.23 frystyk 78: /* ------------------------------------------------------------------------- */
79:
2.79 frystyk 80: PRIVATE int HTBeforeOrder (const void * a, const void * b)
81: {
82: return ((BeforeFilter *) b)->order - ((BeforeFilter *) a)->order;
83: }
84:
85: PRIVATE int HTAfterOrder (const void * a, const void * b)
86: {
87: return ((AfterFilter *) b)->order - ((AfterFilter *) a)->order;
88: }
89:
90: PRIVATE int check_order (int order)
91: {
92: return (order<HT_FILTER_FIRST) ? HT_FILTER_FIRST :
93: (order>HT_FILTER_LAST) ? HT_FILTER_LAST : order;
94: }
95:
96: /*
97: ** Register a BEFORE filter in the list provided by the caller.
98: ** Several filters can be registered in which case they are called
99: ** with the filter ordering in mind.
100: */
101: PUBLIC BOOL HTNetCall_addBefore (HTList * list, HTNetBefore * before,
102: const char * tmplate, void * param,
103: int order)
104: {
105: if (list && before) {
106: BeforeFilter * me;
107: if ((me = (BeforeFilter *) HT_CALLOC(1, sizeof(BeforeFilter)))==NULL)
108: HT_OUTOFMEM("HTNetCall_addBefore");
109: me->before = before;
110: if (tmplate) StrAllocCopy(me->tmplate, tmplate);
111: me->order = check_order(order);
112: me->param = param;
113: if (CORE_TRACE)
114: HTTrace("Net Before.. Add %p with order %d tmplate `%s\' context %p\n",
115: before, me->order, tmplate ? tmplate : "<null>", param);
116: return (HTList_addObject(list, me) &&
117: HTList_insertionSort(list, HTBeforeOrder));
118: }
119: return NO;
120: }
121:
122: /*
123: ** Unregister all instances of a BEFORE filter from a list.
124: */
125: PUBLIC BOOL HTNetCall_deleteBefore (HTList * list, HTNetBefore * before)
126: {
127: if (CORE_TRACE) HTTrace("Net Before.. Delete %p\n", before);
128: if (list && before) {
129: HTList * cur = list;
130: BeforeFilter * pres;
131: while ((pres = (BeforeFilter *) HTList_nextObject(list))) {
132: if (pres->before == before) {
133: HTList_removeObject(list, (void *) pres);
134: HT_FREE(pres->tmplate);
135: HT_FREE(pres);
136: cur = list;
137: }
138: }
139: }
140: return NO;
141: }
142:
143: /*
144: ** Deletes all BEFORE filters in list
145: */
146: PUBLIC BOOL HTNetCall_deleteBeforeAll (HTList * list)
147: {
148: if (CORE_TRACE) HTTrace("Net Before. Delete All filters\n");
149: if (list) {
150: HTList * cur = list;
151: BeforeFilter * pres;
152: while ((pres = (BeforeFilter *) HTList_nextObject(cur))) {
153: HT_FREE(pres->tmplate);
154: HT_FREE(pres);
155: }
156: HTList_delete(list);
157: return YES;
158: }
159: return NO;
160: }
161:
162: /*
163: ** Call all the BEFORE filters in the order specified at registration
164: ** time. We also check for any template and whether it matches or not.
165: ** If a filter returns other than HT_OK then stop and return immediately.
166: ** Otherwise return what the last filter returns.
2.23 frystyk 167: */
2.79 frystyk 168: PUBLIC int HTNetCall_executeBefore (HTList * list, HTRequest * request)
2.23 frystyk 169: {
2.79 frystyk 170: HTParentAnchor * anchor = HTRequest_anchor(request);
171: char * url = HTAnchor_physical(anchor);
172: char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
173: int ret = HT_OK;
174: int mode = 0;
175: if (list && request && addr) {
176: BeforeFilter * pres;
177: while ((pres = (BeforeFilter *) HTList_nextObject(list))) {
178: if (!pres->tmplate ||
179: (pres->tmplate && HTStrMatch(pres->tmplate, addr))) {
180: if (CORE_TRACE) HTTrace("Net Before.. calling %p (request %p, context %p)\n",
181: pres->before,
182: request, pres->param);
183: ret = (*pres->before)(request, pres->param, mode);
184: if (ret != HT_OK) break;
185: }
186: }
187: }
188: if (!url) HT_FREE(addr);
189: return ret;
190: }
191:
192: /*
193: ** Register a AFTER filter in the list provided by the caller.
194: ** Several filters can be registered in which case they are called
195: ** with the filter ordering in mind.
196: */
197: PUBLIC BOOL HTNetCall_addAfter (HTList * list, HTNetAfter * after,
198: const char * tmplate, void * param,
199: int status, int order)
200: {
201: if (list && after) {
202: AfterFilter * me;
203: if ((me = (AfterFilter *) HT_CALLOC(1, sizeof(AfterFilter)))==NULL)
204: HT_OUTOFMEM("HTNetCall_addAfter");
205: me->after = after;
206: if (tmplate) StrAllocCopy(me->tmplate, tmplate);
207: me->order = check_order(order);
2.60 frystyk 208: me->param = param;
2.33 frystyk 209: me->status = status;
2.79 frystyk 210: if (CORE_TRACE)
211: HTTrace("Net After... Add %p with order %d tmplate `%s\' code %d context %p\n",
212: after, me->order, tmplate ? tmplate : "<null>", status, param);
213: return (HTList_addObject(list, me) &&
214: HTList_insertionSort(list, HTAfterOrder));
215: }
216: return NO;
217: }
218:
219: /*
220: ** Unregister all instances of an AFTER filter from a list.
221: */
222: PUBLIC BOOL HTNetCall_deleteAfter (HTList * list, HTNetAfter * after)
223: {
224: if (CORE_TRACE) HTTrace("Net After... Delete %p\n", after);
225: if (list && after) {
226: HTList * cur = list;
227: AfterFilter * pres;
228: while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
229: if (pres->after == after) {
230: HTList_removeObject(list, (void *) pres);
231: HT_FREE(pres->tmplate);
232: HT_FREE(pres);
233: cur = list;
234: }
235: }
2.23 frystyk 236: }
237: return NO;
238: }
239:
2.79 frystyk 240: /*
241: ** Unregister all filters registered for a given status.
2.23 frystyk 242: */
2.79 frystyk 243: PUBLIC BOOL HTNetCall_deleteAfterStatus (HTList * list, int status)
2.23 frystyk 244: {
2.79 frystyk 245: if (CORE_TRACE) HTTrace("Net After... Delete all with status %d\n",status);
246: if (list) {
247: HTList * cur = list;
248: AfterFilter * pres;
249: while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
250: if (pres->status == status) {
2.33 frystyk 251: HTList_removeObject(list, (void *) pres);
2.79 frystyk 252: HT_FREE(pres->tmplate);
2.49 frystyk 253: HT_FREE(pres);
2.79 frystyk 254: cur = list;
2.23 frystyk 255: }
256: }
2.79 frystyk 257: return YES;
2.23 frystyk 258: }
259: return NO;
260: }
2.1 frystyk 261:
2.79 frystyk 262: /*
263: ** Deletes all AFTER filters in list
2.23 frystyk 264: */
2.79 frystyk 265: PUBLIC BOOL HTNetCall_deleteAfterAll (HTList * list)
2.23 frystyk 266: {
2.79 frystyk 267: if (CORE_TRACE) HTTrace("Net After. Delete All filters\n");
2.33 frystyk 268: if (list) {
2.79 frystyk 269: HTList * cur = list;
270: AfterFilter * pres;
271: while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
272: HT_FREE(pres->tmplate);
2.49 frystyk 273: HT_FREE(pres);
2.23 frystyk 274: }
2.33 frystyk 275: HTList_delete(list);
2.23 frystyk 276: return YES;
277: }
278: return NO;
279: }
280:
2.79 frystyk 281: /*
282: ** Call all the AFTER filters in the order specified at registration
283: ** time and if it has the right status code and it's not HT_IGNORE.
284: ** We also check for any template and whether it matches or not.
285: ** If a filter returns other than HT_OK then stop and return immediately.
286: ** Otherwise return what the last filter returns.
2.23 frystyk 287: */
2.79 frystyk 288: PUBLIC int HTNetCall_executeAfter (HTList * list, HTRequest * request,
289: int status)
2.23 frystyk 290: {
2.33 frystyk 291: int ret = HT_OK;
2.79 frystyk 292: if (status != HT_IGNORE) {
293: HTParentAnchor * anchor = HTRequest_anchor(request);
294: char * url = HTAnchor_physical(anchor);
295: char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
296: HTResponse * response = HTRequest_response(request);
297: if (list && request && addr) {
298: AfterFilter * pres;
299: while ((pres = (AfterFilter *) HTList_nextObject(list))) {
300: if ((pres->status == status || pres->status == HT_ALL) &&
301: (!pres->tmplate ||
302: (pres->tmplate && HTStrMatch(pres->tmplate, addr)))) {
303: if (CORE_TRACE)
304: HTTrace("Net After... calling %p (request %p, response %p, status %d, context %p)\n",
305: pres->after, request, response,
306: status, pres->param);
307: ret = (*pres->after)(request, response, pres->param, status);
308: if (ret != HT_OK) break;
309: }
2.23 frystyk 310: }
311: }
2.79 frystyk 312: if (!url) HT_FREE(addr);
2.1 frystyk 313: }
2.33 frystyk 314: return ret;
315: }
316:
2.79 frystyk 317: /* ------------------------------------------------------------------------- */
318: /* GLOBAL BEFORE and AFTER filter Management */
319: /* ------------------------------------------------------------------------- */
320:
2.33 frystyk 321: /*
322: ** Global set of callback functions BEFORE the request is issued
323: ** list can be NULL
324: */
325: PUBLIC BOOL HTNet_setBefore (HTList *list)
326: {
327: HTBefore = list;
328: return YES;
329: }
330:
331: PUBLIC HTList * HTNet_before (void)
332: {
333: return HTBefore;
334: }
335:
2.79 frystyk 336: PUBLIC BOOL HTNet_addBefore (HTNetBefore * before, const char * tmplate,
337: void * param, int order)
2.33 frystyk 338: {
2.79 frystyk 339: if (!HTBefore) HTBefore = HTList_new();
340: return HTNetCall_addBefore(HTBefore, before, tmplate, param, order);
2.33 frystyk 341: }
342:
2.79 frystyk 343: PUBLIC BOOL HTNet_deleteBefore (HTNetBefore * cbf)
2.33 frystyk 344: {
2.79 frystyk 345: return HTNetCall_deleteBefore(HTBefore, cbf);
2.33 frystyk 346: }
347:
2.79 frystyk 348: /*
349: ** Call both the local and the global BEFORE filters (if any)
350: */
351: PUBLIC int HTNet_executeBeforeAll (HTRequest * request)
2.73 frystyk 352: {
2.79 frystyk 353: int ret;
354: BOOL override = NO;
355: HTList * befores;
356: if ((befores = HTRequest_before(request, &override))) {
357: if ((ret = HTNetCall_executeBefore(befores, request)) != HT_OK)
358: return ret;
359: }
360: return override ? HT_OK : HTNetCall_executeBefore(HTBefore, request);
2.73 frystyk 361: }
362:
2.33 frystyk 363: /*
364: ** Global set of callback functions AFTER the request is issued
365: ** list can be NULL
366: */
367: PUBLIC BOOL HTNet_setAfter (HTList *list)
368: {
369: HTAfter = list;
370: return YES;
371: }
372:
373: PUBLIC HTList * HTNet_after (void)
374: {
375: return HTAfter;
376: }
377:
2.79 frystyk 378: PUBLIC BOOL HTNet_addAfter (HTNetAfter * after, const char * tmplate,
379: void * param, int status, int order)
2.33 frystyk 380: {
2.79 frystyk 381: if (!HTAfter) HTAfter = HTList_new();
382: return HTNetCall_addAfter(HTAfter, after, tmplate, param, status, order);
383: }
2.58 hallam 384:
2.79 frystyk 385: PUBLIC BOOL HTNet_deleteAfter (HTNetAfter * cbf)
386: {
387: return HTNetCall_deleteAfter(HTAfter, cbf);
2.33 frystyk 388: }
389:
2.79 frystyk 390: PUBLIC BOOL HTNet_deleteAfterStatus (int status)
2.33 frystyk 391: {
2.79 frystyk 392: return HTNetCall_deleteAfterStatus(HTAfter, status);
2.73 frystyk 393: }
394:
2.79 frystyk 395: /*
396: ** Call both the local and the global AFTER filters (if any)
397: */
398: PUBLIC int HTNet_executeAfterAll (HTRequest * request, int status)
2.73 frystyk 399: {
2.79 frystyk 400: int ret;
401: BOOL override = NO;
402: HTList * afters;
403: if ((afters = HTRequest_after(request, &override))) {
404: if ((ret = HTNetCall_executeAfter(afters, request, status)) != HT_OK)
405: return ret;
406: }
407: return override ? HT_OK : HTNetCall_executeAfter(HTAfter, request, status);
2.1 frystyk 408: }
409:
2.23 frystyk 410: /* ------------------------------------------------------------------------- */
2.74 frystyk 411: /* Socket Management */
2.23 frystyk 412: /* ------------------------------------------------------------------------- */
2.1 frystyk 413:
2.74 frystyk 414: PUBLIC int HTNet_maxSocket (void)
415: {
416: return MaxActive;
417: }
418:
419: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
420: {
421: if (newmax > 0) {
422: MaxActive = newmax;
423: return YES;
424: }
425: return NO;
426: }
427:
428: PUBLIC void HTNet_increaseSocket (void)
429: {
430: Active++;
431: if (CORE_TRACE) HTTrace("Net Manager. %d open sockets\n", Active);
432: }
433:
434: PUBLIC void HTNet_decreaseSocket (void)
435: {
436: if (--Active < 0) Active = 0;
437: if (CORE_TRACE) HTTrace("Net Manager. %d open sockets\n", Active);
438: }
439:
440: PUBLIC int HTNet_availableSockets (void)
441: {
442: int available = MaxActive - Active;
443: return available > 0 ? available : 0;
444: }
445:
446: PUBLIC void HTNet_increasePersistentSocket (void)
447: {
448: Persistent++;
449: if (CORE_TRACE) HTTrace("Net Manager. %d persistent sockets\n", Persistent);
450: }
451:
452: PUBLIC void HTNet_decreasePersistentSocket (void)
2.23 frystyk 453: {
2.74 frystyk 454: if (--Persistent < 0) Persistent = 0;
455: if (CORE_TRACE) HTTrace("Net Manager. %d persistent sockets\n", Persistent);
2.23 frystyk 456: }
2.17 frystyk 457:
2.74 frystyk 458: PUBLIC int HTNet_availablePersistentSockets (void)
2.28 frystyk 459: {
2.74 frystyk 460: int available = MaxActive - 2 - Persistent;
461: return available > 0 ? available : 0;
2.28 frystyk 462: }
463:
2.74 frystyk 464: /*
465: ** Returns whether there are any Net objects pending or active
2.40 frystyk 466: */
2.74 frystyk 467: PUBLIC BOOL HTNet_isIdle (void)
2.40 frystyk 468: {
2.74 frystyk 469: return (HTNetCount > 0);
2.40 frystyk 470: }
471:
2.74 frystyk 472: PUBLIC BOOL HTNet_isEmpty (void)
2.1 frystyk 473: {
2.74 frystyk 474: return (HTNetCount <= 0);
2.79.2.9! eric 475: }
! 476:
! 477: PUBLIC int HTNet_count (void)
! 478: {
! 479: return HTNetCount;
2.1 frystyk 480: }
481:
2.23 frystyk 482: /* ------------------------------------------------------------------------- */
483: /* Creation and deletion methods */
484: /* ------------------------------------------------------------------------- */
485:
2.74 frystyk 486: PRIVATE HTNet * create_object (void)
487: {
488: static int net_hash = 0;
489: HTNet * me = NULL;
490:
491: /* Create new object */
492: if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
493: HT_OUTOFMEM("HTNet_new");
494: me->hash = net_hash++ % HASH_SIZE;
495:
496: /* Insert into hash table */
497: if (!NetTable) {
498: if ((NetTable = (HTList **) HT_CALLOC(HASH_SIZE, sizeof(HTList *))) == NULL)
499: HT_OUTOFMEM("create_object");
500: }
501: if (!NetTable[me->hash]) NetTable[me->hash] = HTList_new();
502: HTList_addObject(NetTable[me->hash], (void *) me);
503: HTNetCount++;
504: if (CORE_TRACE)
505: HTTrace("Net Object.. %p created with hash %d\n",me, me->hash);
506: return me;
507: }
508:
2.27 frystyk 509: /* HTNet_duplicate
510: ** ---------------
511: ** Creates a new HTNet object as a duplicate of the same request.
512: ** Returns YES if OK, else NO
513: ** BUG: We do not check if we have a socket free!
514: */
2.43 frystyk 515: PUBLIC HTNet * HTNet_dup (HTNet * src)
2.27 frystyk 516: {
2.74 frystyk 517: if (src) {
518: HTNet * me;
2.75 frystyk 519: int hash;
2.74 frystyk 520: if ((me = create_object()) == NULL) return NULL;
2.75 frystyk 521: hash = me->hash;
2.74 frystyk 522: if (CORE_TRACE) HTTrace("Net Object.. Duplicated %p\n", src);
523: memcpy((void *) me, src, sizeof(HTNet));
2.75 frystyk 524: me->hash = hash; /* Carry over hash entry */
2.74 frystyk 525: return me;
526: }
527: return NULL;
2.27 frystyk 528: }
529:
2.79.2.6 frystyk 530: PUBLIC BOOL HTNet_execute (HTNet * net, HTEventType type)
531: {
532: if (net && net->event.cbf && net->request) {
533: if (CORE_TRACE)
534: HTTrace("Net Object.. Call %p with event type %d and context %p\n",
535: net->event.cbf, type, net->context);
536: (*(net->event.cbf))(HTNet_socket(net), net->context, type);
537: return YES;
538: }
539: return NO;
540: }
541:
2.74 frystyk 542: /*
543: ** Start a Net obejct by calling the protocol module.
2.30 frystyk 544: */
2.74 frystyk 545: PUBLIC BOOL HTNet_start (HTNet * net)
2.30 frystyk 546: {
2.79.2.1 eric 547: if (net && net->event.cbf && net->request) {
2.74 frystyk 548: if (CORE_TRACE) HTTrace("Net Object.. Launching %p\n", net);
2.79.2.7 eric 549: (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_BEGIN);
2.30 frystyk 550: return YES;
551: }
552: return NO;
553: }
554:
2.37 frystyk 555: /* HTNet_new
556: ** ---------
557: ** This function creates a new HTNet object and assigns the socket number
558: ** to it. This is intended to be used when you are going to listen on a
559: ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
560: ** call any of the callback functions.
561: ** Returns new object or NULL on error
562: */
2.79.2.2 frystyk 563: PUBLIC HTNet * HTNet_new (HTRequest * request)
2.37 frystyk 564: {
2.79.2.2 frystyk 565: HTNet * me;
566: if ((me = create_object()) == NULL) return NULL;
567: me->preemptive = HTRequest_preemptive(request);
568: HTNet_setEventPriority(me, HTRequest_priority(request));
569: me->request = request;
570: HTRequest_setNet(request, me);
571: return me;
2.37 frystyk 572: }
573:
2.67 frystyk 574: /* HTNet_newServer
575: ** ---------------
576: ** Create a new HTNet object as a new request to be handled. If we have
2.74 frystyk 577: ** more than MaxActive connections already then return NO.
2.67 frystyk 578: ** Returns YES if OK, else NO
2.37 frystyk 579: */
2.79.2.1 eric 580:
2.69 frystyk 581: PUBLIC BOOL HTNet_newServer (HTRequest * request, HTNet * net, char * access)
2.37 frystyk 582: {
583: HTProtocol * protocol;
2.67 frystyk 584: HTTransport * tp = NULL; /* added JTD:5/28/96 */
2.79.2.1 eric 585: HTProtCallback * cbf;
2.37 frystyk 586: if (!request) return NO;
587:
588: /* Find a protocol object for this access scheme */
2.46 frystyk 589: protocol = HTProtocol_find(request, access);
2.67 frystyk 590:
591: /* added - JTD:5/28/96 */
592: /* Find a transport object for this protocol */
593: tp = HTTransport_find(request, HTProtocol_transport(protocol));
594: if (tp == NULL) {
2.74 frystyk 595: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT OBJECT\n");
2.67 frystyk 596: return NO;
597: }
598: /* end of additions - JTD:5/28/96 */
599:
2.69 frystyk 600: /* Fill out the net object and bind it to the request object */
2.74 frystyk 601: net->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.79.2.1 eric 602: #if 0
2.69 frystyk 603: net->protocol = protocol;
604: net->transport = tp; /* added - JTD:5/28/96 */
2.79.2.1 eric 605: #endif
606: net->event.priority = HTRequest_priority(request);
2.69 frystyk 607: net->request = request;
608: HTRequest_setNet(request, net);
2.79.2.1 eric 609: if (!(cbf = HTProtocol_server(protocol))) {
2.74 frystyk 610: if (CORE_TRACE) HTTrace("Net Object.. NO CALL BACK FUNCTION!\n");
2.67 frystyk 611: return NO;
2.37 frystyk 612: }
2.74 frystyk 613:
614: /* Increase the number of retrys for this download */
615: HTRequest_addRetry(request);
2.37 frystyk 616:
617: /* Start the server request */
2.58 hallam 618: if (CORE_TRACE)
2.74 frystyk 619: HTTrace("Net Object.. starting SERVER request %p with net object %p\n", request, net);
2.79.2.1 eric 620: (*(cbf))(HTNet_socket(net), request);
2.37 frystyk 621: return YES;
622: }
2.36 frystyk 623:
2.30 frystyk 624: /* HTNet_new
625: ** ---------
2.23 frystyk 626: ** Create a new HTNet object as a new request to be handled. If we have
2.74 frystyk 627: ** more than MaxActive connections already then put this into the
2.23 frystyk 628: ** pending queue, else start the request by calling the call back
629: ** function registered with this access method.
630: ** Returns YES if OK, else NO
631: */
2.37 frystyk 632: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23 frystyk 633: {
2.74 frystyk 634: HTParentAnchor * anchor = HTRequest_anchor(request);
2.59 frystyk 635: HTNet * me = NULL;
636: HTProtocol * protocol = NULL;
637: HTTransport * tp = NULL;
2.37 frystyk 638: char * physical = NULL;
2.74 frystyk 639: int status;
2.79.2.1 eric 640: HTProtCallback * cbf;
641:
2.27 frystyk 642: if (!request) return NO;
2.33 frystyk 643: /*
644: ** First we do all the "BEFORE" callbacks in order to see if we are to
645: ** continue with this request or not. If we receive a callback status
646: ** that is NOT HT_OK then jump directly to the after callbacks and return
647: */
2.79 frystyk 648: if ((status = HTNet_executeBeforeAll(request)) != HT_OK) {
649: HTNet_executeAfterAll(request, status);
2.33 frystyk 650: return YES;
651: }
652:
2.36 frystyk 653: /*
2.79 frystyk 654: ** If no translation was provided by the filters then use the anchor
2.36 frystyk 655: ** address directly
656: */
2.74 frystyk 657: if (!(physical = HTAnchor_physical(anchor))) {
658: char * addr = HTAnchor_address((HTAnchor *) anchor);
659: if (CORE_TRACE) HTTrace("Net Object.. Using default address\n");
660: HTAnchor_setPhysical(anchor, addr);
661: physical = HTAnchor_physical(anchor);
2.49 frystyk 662: HT_FREE(addr);
2.33 frystyk 663: }
664:
2.37 frystyk 665: /* Find a protocol object for this access scheme */
666: {
667: char * access = HTParse(physical, "", PARSE_ACCESS);
668: if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.74 frystyk 669: if (CORE_TRACE) HTTrace("Net Object.. NO PROTOCOL OBJECT\n");
2.49 frystyk 670: HT_FREE(access);
2.37 frystyk 671: return NO;
672: }
2.49 frystyk 673: HT_FREE(access);
2.37 frystyk 674: }
2.59 frystyk 675:
676: /* Find a transport object for this protocol */
677: tp = HTTransport_find(request, HTProtocol_transport(protocol));
678: if (tp == NULL) {
2.74 frystyk 679: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT OBJECT\n");
2.59 frystyk 680: return NO;
681: }
682:
2.23 frystyk 683: /* Create new net object and bind it to the request object */
2.69 frystyk 684: if ((me = create_object()) == NULL) return NO;
2.74 frystyk 685: me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.79.2.1 eric 686: #if 0
2.69 frystyk 687: me->priority = HTRequest_priority(request);
2.79.2.1 eric 688: #endif
689: HTNet_setEventPriority(me, HTRequest_priority(request));
2.59 frystyk 690: me->protocol = protocol;
691: me->transport = tp;
2.69 frystyk 692: me->request = request;
693: HTRequest_setNet(request, me);
2.79.2.1 eric 694: if (!(cbf = HTProtocol_client(protocol))) {
2.74 frystyk 695: if (CORE_TRACE) HTTrace("Net Object.. NO CALL BACK FUNCTION!\n");
2.49 frystyk 696: HT_FREE(me);
2.23 frystyk 697: return NO;
698: }
2.74 frystyk 699:
700: /* Increase the number of retrys for this download */
701: HTRequest_addRetry(request);
2.23 frystyk 702:
703: /*
704: ** Check if we can start the request, else put it into pending queue
705: ** If so then call the call back function associated with the anchor.
706: ** We use the INVSOC as we don't have a valid socket yet!
707: */
2.74 frystyk 708: if (CORE_TRACE)
709: HTTrace("Net Object.. starting request %p (retry=%d) with net object %p\n",
710: request, HTRequest_retrys(request), me);
2.79.2.1 eric 711: (*(cbf))(INVSOC, request);
2.36 frystyk 712: return YES;
713: }
714:
2.23 frystyk 715: /* delete_object
716: ** -------------
717: ** Deletes an HTNet object
2.40 frystyk 718: ** Return YES if OK, else NO
2.15 frystyk 719: */
2.79.2.5 frystyk 720: PRIVATE BOOL delete_object (HTNet * net)
2.15 frystyk 721: {
2.74 frystyk 722: if (CORE_TRACE) HTTrace("Net Object.. Remove object %p\n", net);
2.23 frystyk 723: if (net) {
724:
725: /* Close socket */
2.74 frystyk 726: /*
727: ** As we may have a socket available we check for whether
728: ** we can start any pending requests. We do this by asking for
729: ** pending Host objects. If none then use the current object
730: */
2.79.2.1 eric 731: /* (*net->input->isa->consumed)(net->input, net->header_length + net->bytes_read);
732: */
2.74 frystyk 733: HTHost_launchPending(net->host);
734:
735: /*
736: ** Break the link to the request and free the Net object
737: */
738: HTRequest_setNet(net->request, NULL);
2.49 frystyk 739: HT_FREE(net);
2.79.2.5 frystyk 740: return YES;
741: }
742: return NO;
743: }
744:
745: PRIVATE BOOL remove_net (HTNet * net)
746: {
747: if (net && NetTable) {
748: HTList * list = NetTable[net->hash];
749: if (list) {
750: HTList_removeObject(list, (void *) net);
751: delete_object(net);
752: HTNetCount--;
753: return YES;
754: }
2.23 frystyk 755: }
756: return NO;
757: }
758:
2.74 frystyk 759: /*
760: ** Clears the contents of the Net object so that we can use it again.
761: */
762: PUBLIC BOOL HTNet_clear (HTNet * net)
763: {
764: if (net) {
2.79.2.1 eric 765: net->host->channel = NULL;
766: net->readStream = NULL;
767: net->bytesRead = 0;
768: net->bytesWritten = 0;
769: net->headerLength = 0;
2.74 frystyk 770: return YES;
771: }
772: return NO;
773: }
774:
2.23 frystyk 775: /* HTNet_delete
776: ** ------------
777: ** Deletes the HTNet object from the list of active requests and calls
778: ** any registered call back functions IF not the status is HT_IGNORE.
779: ** This is used if we have internal requests that the app doesn't know
780: ** about. We also see if we have pending requests that can be started
781: ** up now when we have a socket free.
782: ** The callback functions are called in the reverse order of which they
783: ** were registered (last one first)
2.40 frystyk 784: ** Return YES if OK, else NO
2.23 frystyk 785: */
786: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
787: {
2.58 hallam 788: if (CORE_TRACE)
2.74 frystyk 789: HTTrace("Net Object.. Delete %p and call AFTER filters\n", net);
790: if (net) {
791: HTRequest * request = net->request;
2.23 frystyk 792:
2.25 frystyk 793: /*
2.74 frystyk 794: ** If we have a premature close then recover the request. Otherwise
795: ** break the link to the Host object and continue deleting the net
796: ** object
2.25 frystyk 797: */
2.74 frystyk 798: if (net->host) {
799: if (status == HT_RECOVER_PIPE) {
800: if (CORE_TRACE) HTTrace("Net Object.. Recovering %p\n", net);
2.79.2.1 eric 801: HTChannel_setSemaphore(net->host->channel, 0);
2.74 frystyk 802: HTHost_clearChannel(net->host, HT_INTERRUPTED);
803: HTHost_setMode(net->host, HT_TP_SINGLE);
804: HTNet_clear(net);
2.58 hallam 805: if (CORE_TRACE)
2.74 frystyk 806: HTTrace("Net Object.. Restarting request %p (retry=%d) with net object %p\n",
807: request, HTRequest_retrys(request), net);
2.78 frystyk 808: #if 0
2.74 frystyk 809: HTHost_launchPending(net->host);
810: return YES;
2.78 frystyk 811: #else
812: return HTNet_start(net);
813: #endif
2.79.2.1 eric 814: }
2.79.2.3 eric 815: HTHost_unregister (net->host, net, HTEvent_READ);
816: HTHost_unregister (net->host, net, HTEvent_WRITE);
2.79.2.1 eric 817: HTHost_free(net->host, status);
818: HTHost_deleteNet(net->host, net);
2.74 frystyk 819: }
820:
821: /* Remove object from the table of Net Objects */
2.79.2.5 frystyk 822: remove_net(net);
823: #if 0
2.74 frystyk 824: if (NetTable) {
825: HTList * list = NetTable[net->hash];
826: if (list) {
827: HTList_removeObject(list, (void *) net);
2.79.2.5 frystyk 828: delete_object(net);
2.74 frystyk 829: HTNetCount--;
2.23 frystyk 830: }
831: }
2.79.2.5 frystyk 832: #endif
2.74 frystyk 833:
834: /* Call AFTER filters */
2.79 frystyk 835: HTNet_executeAfterAll(request, status);
2.74 frystyk 836: return YES;
2.23 frystyk 837: }
838: return NO;
839: }
840:
841: /* HTNet_deleteAll
842: ** ---------------
843: ** Deletes all HTNet object that might either be active or pending
2.74 frystyk 844: ** We DO NOT call the AFTER filters - A crude way of saying goodbye!
2.23 frystyk 845: */
846: PUBLIC BOOL HTNet_deleteAll (void)
847: {
2.58 hallam 848: if (CORE_TRACE)
2.74 frystyk 849: HTTrace("Net Object.. Remove all Net objects, NO filters\n");
850: if (NetTable) {
851: HTList * cur = NULL;
852: HTNet * pres = NULL;
853: int cnt;
854: for (cnt=0; cnt<HASH_SIZE; cnt++) {
855: if ((cur = NetTable[cnt])) {
856: while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)
2.79.2.5 frystyk 857: delete_object(pres);
2.74 frystyk 858: }
859: HTList_delete(NetTable[cnt]);
2.25 frystyk 860: }
2.74 frystyk 861: HT_FREE(NetTable);
862: HTNetCount = 0;
863: return YES;
2.25 frystyk 864: }
865: return NO;
866: }
867:
2.23 frystyk 868: /* HTNet_kill
869: ** ----------
870: ** Kill the request by calling the call back function with a request for
871: ** closing the connection. Does not remove the object. This is done by
872: ** HTNet_delete() function which is called by the load routine.
873: ** Returns OK if success, NO on error
874: */
2.74 frystyk 875: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23 frystyk 876: {
2.79.2.5 frystyk 877: if (net) {
878: if (CORE_TRACE) HTTrace("Net Object.. Killing %p\n", net);
879: if (net->event.cbf) {
880: (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_CLOSE);
881: return YES;
882: }
883: return remove_net(net);
2.23 frystyk 884: }
2.79.2.2 frystyk 885: if (CORE_TRACE) HTTrace("Net Object.. No object to kill\n");
2.23 frystyk 886: return NO;
887: }
888:
889: /* HTNet_killAll
890: ** -------------
2.74 frystyk 891: ** Kills all registered net objects by calling the call
2.23 frystyk 892: ** back function with a request for closing the connection. We do not
893: ** remove the HTNet object as it is done by HTNet_delete().
894: ** Returns OK if success, NO on error
895: */
896: PUBLIC BOOL HTNet_killAll (void)
897: {
2.74 frystyk 898: if (CORE_TRACE) HTTrace("Net Object.. Kill ALL Net objects!!!\n");
899: if (NetTable) {
900: HTList * cur = NULL;
901: HTNet * pres = NULL;
902: int cnt;
903: for (cnt=0; cnt<HASH_SIZE; cnt++) {
904: if ((cur = NetTable[cnt])) {
2.75 frystyk 905: while ((pres = (HTNet *) HTList_lastObject(cur)) != NULL)
2.74 frystyk 906: HTNet_kill(pres);
907: }
2.25 frystyk 908: }
2.74 frystyk 909: return YES;
2.25 frystyk 910: }
2.74 frystyk 911: if (CORE_TRACE) HTTrace("Net Object.. No objects to kill\n");
912: return NO;
2.23 frystyk 913: }
2.38 frystyk 914:
915: /* ------------------------------------------------------------------------- */
2.59 frystyk 916: /* Connection Specifics */
917: /* ------------------------------------------------------------------------- */
918:
2.74 frystyk 919: /* HTNet_priority
920: ** --------------
921: ** Get the current priority of the Net object
922: */
923: PUBLIC HTPriority HTNet_priority (HTNet * net)
924: {
2.79.2.1 eric 925: return (net ? net->event.priority : HT_PRIORITY_INV);
2.74 frystyk 926: }
927:
928: /* HTNet_setPriority
929: ** -----------------
930: ** Set the current priority of the Net object
931: ** This will change the priority next time the thread is blocked
932: */
933: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
934: {
935: if (net) {
2.79.2.1 eric 936: net->event.priority = priority;
2.74 frystyk 937: return YES;
938: }
939: return NO;
940: }
941:
2.59 frystyk 942: /* HTNet_Persistent
943: ** ----------------
944: ** Check whether the net object handles persistent connections
945: ** If we have a DNS entry then check that as well.
946: */
947: PUBLIC BOOL HTNet_persistent (HTNet * net)
948: {
949: return (net && HTHost_isPersistent(net->host));
950: }
951:
952: /* HTNet_persistent
953: ** ----------------
954: ** Set the net object to handle persistent connections
955: ** If we also have a DNS entry then update that as well
956: */
2.74 frystyk 957: PUBLIC BOOL HTNet_setPersistent (HTNet * net,
958: BOOL persistent,
959: HTTransportMode mode)
2.59 frystyk 960: {
961: if (net) {
2.79.2.1 eric 962: BOOL result = HTHost_setPersistent(net->host, persistent, mode);
2.74 frystyk 963: if (CORE_TRACE)
964: HTTrace("Net Object.. Persistent connection set %s %s\n",
965: persistent ? "ON" : "OFF",
966: result ? "succeeded" : "failed");
2.79.2.1 eric 967: return result;
2.59 frystyk 968: }
969: return NO;
970: }
971:
2.66 frystyk 972: /*
973: ** Context pointer to be used in context call back function
974: */
975: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
976: {
977: if (net) {
978: net->context = context;
979: return YES;
980: }
981: return NO;
982: }
983:
984: PUBLIC void * HTNet_context (HTNet * net)
985: {
986: return net ? net->context : NULL;
987: }
2.38 frystyk 988:
989: /*
2.60 frystyk 990: ** Get and set the socket number
991: */
992: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
993: {
2.79.2.1 eric 994: if (net && net->host && net->host->channel) {
995: HTChannel_setSocket(net->host->channel, sockfd);
2.60 frystyk 996: return YES;
997: }
998: return NO;
999: }
1000:
1001: PUBLIC SOCKET HTNet_socket (HTNet * net)
1002: {
2.79.2.1 eric 1003: return (net && net->host && net->host->channel ? HTChannel_socket(net->host->channel) : INVSOC);
2.69 frystyk 1004: }
1005:
1006: /*
1007: ** Get and set the HTRequest object
1008: */
1009: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
1010: {
1011: if (net && request) {
1012: net->request = request;
1013: return YES;
1014: }
1015: return NO;
1016: }
1017:
1018: PUBLIC HTRequest * HTNet_request (HTNet * net)
1019: {
1020: return (net ? net->request : NULL);
2.60 frystyk 1021: }
1022:
2.79.2.1 eric 1023: #if 0
2.60 frystyk 1024: /*
2.59 frystyk 1025: ** Get and set the HTTransport object
2.38 frystyk 1026: */
2.79.2.1 eric 1027: PUBLIC BOOL HTHost_setTransport (HTHost * me, HTTransport * tp)
2.38 frystyk 1028: {
2.79.2.1 eric 1029: if (me && tp) {
1030: me->transport = tp;
2.38 frystyk 1031: return YES;
1032: }
1033: return NO;
1034: }
1035:
2.79.2.1 eric 1036: PUBLIC HTTransport * HTHost_transport (HTHost * me)
2.38 frystyk 1037: {
2.79.2.1 eric 1038: return (me ? me->transport : NULL);
2.38 frystyk 1039: }
2.79.2.1 eric 1040: #endif
2.38 frystyk 1041:
2.55 frystyk 1042: /*
2.59 frystyk 1043: ** Get and set the HTChannel object
2.55 frystyk 1044: */
2.59 frystyk 1045: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55 frystyk 1046: {
2.79.2.8 frystyk 1047: return (net && channel) ? HTHost_setChannel(net->host, channel) : NO;
2.55 frystyk 1048: }
1049:
2.59 frystyk 1050: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55 frystyk 1051: {
2.79.2.8 frystyk 1052: return net ? HTHost_channel(net->host) : NULL;
2.59 frystyk 1053: }
1054:
1055: /*
1056: ** Get and set the HTHost object
1057: */
1058: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
1059: {
1060: if (net && host) {
1061: net->host = host;
1062: return YES;
1063: }
1064: return NO;
1065: }
1066:
1067: PUBLIC HTHost * HTNet_host (HTNet * net)
1068: {
1069: return (net ? net->host : NULL);
1070: }
1071:
1072: /*
1073: ** Get and set the HTdns object
1074: */
1075: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
1076: {
1077: if (net && dns) {
2.79.2.1 eric 1078: net->host->dns = dns;
2.59 frystyk 1079: return YES;
1080: }
1081: return NO;
1082: }
1083:
1084: PUBLIC HTdns * HTNet_dns (HTNet * net)
1085: {
2.79.2.1 eric 1086: return (net ? net->host->dns : NULL);
2.79.2.4 frystyk 1087: }
1088:
1089: PUBLIC BOOL HTNet_setProtocol (HTNet * net, HTProtocol * protocol)
1090: {
1091: if (net && protocol) {
1092: net->protocol = protocol;
1093: return YES;
1094: }
1095: return NO;
1096: }
1097:
1098: PUBLIC HTProtocol * HTNet_protocol (HTNet * net)
1099: {
1100: return (net ? net->protocol : NULL);
2.59 frystyk 1101: }
1102:
2.72 frystyk 1103: PUBLIC int HTNet_home (HTNet * net)
1104: {
1105: return (net ? net->home : 0);
1106: }
2.59 frystyk 1107:
1108: /*
1109: ** Create the output stream and bind it to the channel
1110: ** Please read the description in the HTIOStream module on the parameters
1111: */
2.79.2.1 eric 1112: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * me, void * param, int mode)
2.59 frystyk 1113: {
2.79.2.1 eric 1114: if (me && me->host && me->host->channel && me->transport) {
1115: HTTransport * tp = me->transport;
1116: HTChannel * ch = me->host->channel;
2.79.2.2 frystyk 1117: HTOutputStream * output = (*tp->output_new)(me->host, ch, param, mode);
2.74 frystyk 1118: HTChannel_setOutput(ch, output);
2.59 frystyk 1119: return output;
1120: }
2.79.2.1 eric 1121: if (CORE_TRACE) HTTrace("Host Object.. Can't create output stream\n");
2.59 frystyk 1122: return NULL;
2.55 frystyk 1123: }
2.79.2.1 eric 1124:
1125: PUBLIC BOOL HTNet_setEventParam(HTNet * net, void * eventParam)
1126: {
1127: if (net) return HTEvent_setParam(&net->event, eventParam);
1128: return NO;
1129: }
1130:
1131: PUBLIC void* HTNet_eventParam(HTNet * net)
1132: {
1133: return net->event.param;
1134: }
1135:
1136: PUBLIC BOOL HTNet_setEventCallback(HTNet * net, HTEventCallback * cbf)
1137: {
1138: if (net) return HTEvent_setCallback(&net->event, cbf);
1139: return NO;
1140: }
1141:
1142: PUBLIC HTEventCallback * HTNet_eventCallback(HTNet * net)
1143: {
1144: return net->event.cbf;
1145: }
1146:
1147: PUBLIC BOOL HTNet_setEventPriority(HTNet * net, HTPriority priority)
1148: {
1149: if (net) return HTEvent_setPriority(&net->event, priority);
1150: return NO;
1151: }
1152:
1153: PUBLIC HTPriority HTNet_eventPriority(HTNet * net)
1154: {
1155: return net->event.priority;
1156: }
1157:
2.79.2.2 frystyk 1158: PUBLIC HTStream * HTNet_readStream(HTNet * net)
2.79.2.1 eric 1159: {
1160: if (!net) return NULL;
1161: return net->readStream;
1162: }
1163:
2.79.2.2 frystyk 1164: PUBLIC BOOL HTNet_setReadStream (HTNet * net, HTStream * stream)
1165: {
1166: if (net) {
1167: net->readStream = stream;
1168: return YES;
1169: }
1170: return NO;
1171: }
Webmaster