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