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