Annotation of libwww/Library/src/HTNet.c, revision 2.100
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.100 ! frystyk 6: ** @(#) $Id: HTNet.c,v 2.99 1999/01/15 03:54:46 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;
117: if (CORE_TRACE)
118: HTTrace("Net Before.. Add %p with order %d tmplate `%s\' context %p\n",
119: before, me->order, tmplate ? tmplate : "<null>", param);
120: return (HTList_addObject(list, me) &&
121: HTList_insertionSort(list, HTBeforeOrder));
122: }
123: return NO;
124: }
125:
126: /*
127: ** Unregister all instances of a BEFORE filter from a list.
128: */
129: PUBLIC BOOL HTNetCall_deleteBefore (HTList * list, HTNetBefore * before)
130: {
131: if (CORE_TRACE) HTTrace("Net Before.. Delete %p\n", before);
132: if (list && before) {
133: HTList * cur = list;
134: BeforeFilter * pres;
2.94 frystyk 135: while ((pres = (BeforeFilter *) HTList_nextObject(cur))) {
2.79 frystyk 136: if (pres->before == before) {
137: HTList_removeObject(list, (void *) pres);
138: HT_FREE(pres->tmplate);
139: HT_FREE(pres);
140: cur = list;
141: }
142: }
143: }
144: return NO;
145: }
146:
147: /*
148: ** Deletes all BEFORE filters in list
149: */
150: PUBLIC BOOL HTNetCall_deleteBeforeAll (HTList * list)
151: {
152: if (CORE_TRACE) HTTrace("Net Before. Delete All filters\n");
153: if (list) {
154: HTList * cur = list;
155: BeforeFilter * pres;
156: while ((pres = (BeforeFilter *) HTList_nextObject(cur))) {
157: HT_FREE(pres->tmplate);
158: HT_FREE(pres);
159: }
160: HTList_delete(list);
161: return YES;
162: }
163: return NO;
164: }
165:
166: /*
167: ** Call all the BEFORE filters in the order specified at registration
168: ** time. We also check for any template and whether it matches or not.
169: ** If a filter returns other than HT_OK then stop and return immediately.
170: ** Otherwise return what the last filter returns.
2.23 frystyk 171: */
2.79 frystyk 172: PUBLIC int HTNetCall_executeBefore (HTList * list, HTRequest * request)
2.23 frystyk 173: {
2.79 frystyk 174: HTParentAnchor * anchor = HTRequest_anchor(request);
175: char * url = HTAnchor_physical(anchor);
176: char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
177: int ret = HT_OK;
178: int mode = 0;
179: if (list && request && addr) {
180: BeforeFilter * pres;
181: while ((pres = (BeforeFilter *) HTList_nextObject(list))) {
182: if (!pres->tmplate ||
183: (pres->tmplate && HTStrMatch(pres->tmplate, addr))) {
184: if (CORE_TRACE) HTTrace("Net Before.. calling %p (request %p, context %p)\n",
185: pres->before,
186: request, pres->param);
187: ret = (*pres->before)(request, pres->param, mode);
188: if (ret != HT_OK) break;
2.88 frystyk 189:
190: /*
191: ** Update the address to match against if the filter changed
192: ** the physical address.
193: */
194: if ((url = HTAnchor_physical(anchor))) addr = url;
2.79 frystyk 195: }
196: }
197: }
198: if (!url) HT_FREE(addr);
199: return ret;
200: }
201:
202: /*
203: ** Register a AFTER filter in the list provided by the caller.
204: ** Several filters can be registered in which case they are called
205: ** with the filter ordering in mind.
206: */
207: PUBLIC BOOL HTNetCall_addAfter (HTList * list, HTNetAfter * after,
208: const char * tmplate, void * param,
2.80 frystyk 209: int status, HTFilterOrder order)
2.79 frystyk 210: {
211: if (list && after) {
212: AfterFilter * me;
213: if ((me = (AfterFilter *) HT_CALLOC(1, sizeof(AfterFilter)))==NULL)
214: HT_OUTOFMEM("HTNetCall_addAfter");
215: me->after = after;
216: if (tmplate) StrAllocCopy(me->tmplate, tmplate);
217: me->order = check_order(order);
2.60 frystyk 218: me->param = param;
2.33 frystyk 219: me->status = status;
2.79 frystyk 220: if (CORE_TRACE)
221: HTTrace("Net After... Add %p with order %d tmplate `%s\' code %d context %p\n",
222: after, me->order, tmplate ? tmplate : "<null>", status, param);
223: return (HTList_addObject(list, me) &&
224: HTList_insertionSort(list, HTAfterOrder));
225: }
226: return NO;
227: }
228:
229: /*
230: ** Unregister all instances of an AFTER filter from a list.
231: */
232: PUBLIC BOOL HTNetCall_deleteAfter (HTList * list, HTNetAfter * after)
233: {
234: if (CORE_TRACE) HTTrace("Net After... Delete %p\n", after);
235: if (list && after) {
236: HTList * cur = list;
237: AfterFilter * pres;
238: while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
239: if (pres->after == after) {
240: HTList_removeObject(list, (void *) pres);
241: HT_FREE(pres->tmplate);
242: HT_FREE(pres);
243: cur = list;
244: }
245: }
2.23 frystyk 246: }
247: return NO;
248: }
249:
2.79 frystyk 250: /*
251: ** Unregister all filters registered for a given status.
2.23 frystyk 252: */
2.79 frystyk 253: PUBLIC BOOL HTNetCall_deleteAfterStatus (HTList * list, int status)
2.23 frystyk 254: {
2.79 frystyk 255: if (CORE_TRACE) HTTrace("Net After... Delete all with status %d\n",status);
256: if (list) {
257: HTList * cur = list;
258: AfterFilter * pres;
259: while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
260: if (pres->status == status) {
2.33 frystyk 261: HTList_removeObject(list, (void *) pres);
2.79 frystyk 262: HT_FREE(pres->tmplate);
2.49 frystyk 263: HT_FREE(pres);
2.79 frystyk 264: cur = list;
2.23 frystyk 265: }
266: }
2.79 frystyk 267: return YES;
2.23 frystyk 268: }
269: return NO;
270: }
2.1 frystyk 271:
2.79 frystyk 272: /*
273: ** Deletes all AFTER filters in list
2.23 frystyk 274: */
2.79 frystyk 275: PUBLIC BOOL HTNetCall_deleteAfterAll (HTList * list)
2.23 frystyk 276: {
2.79 frystyk 277: if (CORE_TRACE) HTTrace("Net After. Delete All filters\n");
2.33 frystyk 278: if (list) {
2.79 frystyk 279: HTList * cur = list;
280: AfterFilter * pres;
281: while ((pres = (AfterFilter *) HTList_nextObject(cur))) {
282: HT_FREE(pres->tmplate);
2.49 frystyk 283: HT_FREE(pres);
2.23 frystyk 284: }
2.33 frystyk 285: HTList_delete(list);
2.23 frystyk 286: return YES;
287: }
288: return NO;
289: }
290:
2.79 frystyk 291: /*
292: ** Call all the AFTER filters in the order specified at registration
293: ** time and if it has the right status code and it's not HT_IGNORE.
294: ** We also check for any template and whether it matches or not.
295: ** If a filter returns other than HT_OK then stop and return immediately.
296: ** Otherwise return what the last filter returns.
2.23 frystyk 297: */
2.79 frystyk 298: PUBLIC int HTNetCall_executeAfter (HTList * list, HTRequest * request,
299: int status)
2.23 frystyk 300: {
2.33 frystyk 301: int ret = HT_OK;
2.79 frystyk 302: if (status != HT_IGNORE) {
303: HTParentAnchor * anchor = HTRequest_anchor(request);
304: char * url = HTAnchor_physical(anchor);
305: char * addr = url ? url : HTAnchor_address((HTAnchor *) anchor);
306: HTResponse * response = HTRequest_response(request);
307: if (list && request && addr) {
308: AfterFilter * pres;
309: while ((pres = (AfterFilter *) HTList_nextObject(list))) {
310: if ((pres->status == status || pres->status == HT_ALL) &&
311: (!pres->tmplate ||
312: (pres->tmplate && HTStrMatch(pres->tmplate, addr)))) {
313: if (CORE_TRACE)
314: HTTrace("Net After... calling %p (request %p, response %p, status %d, context %p)\n",
315: pres->after, request, response,
316: status, pres->param);
317: ret = (*pres->after)(request, response, pres->param, status);
318: if (ret != HT_OK) break;
2.88 frystyk 319:
320: /*
321: ** Update the address to match against if the filter changed
322: ** the physical address.
323: */
324: if ((url = HTAnchor_physical(anchor))) addr = url;
2.79 frystyk 325: }
2.23 frystyk 326: }
327: }
2.79 frystyk 328: if (!url) HT_FREE(addr);
2.1 frystyk 329: }
2.33 frystyk 330: return ret;
331: }
332:
2.79 frystyk 333: /* ------------------------------------------------------------------------- */
334: /* GLOBAL BEFORE and AFTER filter Management */
335: /* ------------------------------------------------------------------------- */
336:
2.33 frystyk 337: /*
338: ** Global set of callback functions BEFORE the request is issued
339: ** list can be NULL
340: */
341: PUBLIC BOOL HTNet_setBefore (HTList *list)
342: {
343: HTBefore = list;
344: return YES;
345: }
346:
347: PUBLIC HTList * HTNet_before (void)
348: {
349: return HTBefore;
350: }
351:
2.79 frystyk 352: PUBLIC BOOL HTNet_addBefore (HTNetBefore * before, const char * tmplate,
2.80 frystyk 353: void * param, HTFilterOrder order)
2.33 frystyk 354: {
2.79 frystyk 355: if (!HTBefore) HTBefore = HTList_new();
356: return HTNetCall_addBefore(HTBefore, before, tmplate, param, order);
2.33 frystyk 357: }
358:
2.79 frystyk 359: PUBLIC BOOL HTNet_deleteBefore (HTNetBefore * cbf)
2.33 frystyk 360: {
2.79 frystyk 361: return HTNetCall_deleteBefore(HTBefore, cbf);
2.33 frystyk 362: }
363:
2.79 frystyk 364: /*
365: ** Call both the local and the global BEFORE filters (if any)
366: */
367: PUBLIC int HTNet_executeBeforeAll (HTRequest * request)
2.73 frystyk 368: {
2.79 frystyk 369: int ret;
370: BOOL override = NO;
371: HTList * befores;
372: if ((befores = HTRequest_before(request, &override))) {
373: if ((ret = HTNetCall_executeBefore(befores, request)) != HT_OK)
374: return ret;
375: }
376: return override ? HT_OK : HTNetCall_executeBefore(HTBefore, request);
2.73 frystyk 377: }
378:
2.33 frystyk 379: /*
380: ** Global set of callback functions AFTER the request is issued
381: ** list can be NULL
382: */
383: PUBLIC BOOL HTNet_setAfter (HTList *list)
384: {
385: HTAfter = list;
386: return YES;
387: }
388:
389: PUBLIC HTList * HTNet_after (void)
390: {
391: return HTAfter;
392: }
393:
2.79 frystyk 394: PUBLIC BOOL HTNet_addAfter (HTNetAfter * after, const char * tmplate,
2.80 frystyk 395: void * param, int status, HTFilterOrder order)
2.33 frystyk 396: {
2.79 frystyk 397: if (!HTAfter) HTAfter = HTList_new();
398: return HTNetCall_addAfter(HTAfter, after, tmplate, param, status, order);
399: }
2.58 hallam 400:
2.79 frystyk 401: PUBLIC BOOL HTNet_deleteAfter (HTNetAfter * cbf)
402: {
403: return HTNetCall_deleteAfter(HTAfter, cbf);
2.33 frystyk 404: }
405:
2.79 frystyk 406: PUBLIC BOOL HTNet_deleteAfterStatus (int status)
2.33 frystyk 407: {
2.79 frystyk 408: return HTNetCall_deleteAfterStatus(HTAfter, status);
2.73 frystyk 409: }
410:
2.79 frystyk 411: /*
412: ** Call both the local and the global AFTER filters (if any)
413: */
414: PUBLIC int HTNet_executeAfterAll (HTRequest * request, int status)
2.73 frystyk 415: {
2.79 frystyk 416: int ret;
417: BOOL override = NO;
418: HTList * afters;
419: if ((afters = HTRequest_after(request, &override))) {
420: if ((ret = HTNetCall_executeAfter(afters, request, status)) != HT_OK)
421: return ret;
422: }
423: return override ? HT_OK : HTNetCall_executeAfter(HTAfter, request, status);
2.1 frystyk 424: }
425:
2.23 frystyk 426: /* ------------------------------------------------------------------------- */
2.74 frystyk 427: /* Socket Management */
2.23 frystyk 428: /* ------------------------------------------------------------------------- */
2.1 frystyk 429:
2.74 frystyk 430: PUBLIC int HTNet_maxSocket (void)
431: {
432: return MaxActive;
433: }
434:
435: PUBLIC BOOL HTNet_setMaxSocket (int newmax)
436: {
437: if (newmax > 0) {
438: MaxActive = newmax;
439: return YES;
440: }
441: return NO;
442: }
443:
444: PUBLIC void HTNet_increaseSocket (void)
445: {
446: Active++;
2.87 frystyk 447: if (CORE_TRACE)
448: HTTrace("Net Manager. Increasing active sockets to %d, %d persistent sockets\n",
449: Active, Persistent);
2.74 frystyk 450: }
451:
452: PUBLIC void HTNet_decreaseSocket (void)
453: {
454: if (--Active < 0) Active = 0;
2.87 frystyk 455: if (CORE_TRACE)
456: HTTrace("Net Manager. Decreasing active sockets to %d, %d persistent sockets\n",
457: Active, Persistent);
2.74 frystyk 458: }
459:
460: PUBLIC int HTNet_availableSockets (void)
461: {
462: int available = MaxActive - Active;
463: return available > 0 ? available : 0;
464: }
465:
466: PUBLIC void HTNet_increasePersistentSocket (void)
467: {
468: Persistent++;
2.87 frystyk 469: if (CORE_TRACE)
470: HTTrace("Net Manager. %d active sockets, increasing persistent sockets to %d\n",
471: Active, Persistent);
2.74 frystyk 472: }
473:
474: PUBLIC void HTNet_decreasePersistentSocket (void)
2.23 frystyk 475: {
2.74 frystyk 476: if (--Persistent < 0) Persistent = 0;
2.87 frystyk 477: if (CORE_TRACE)
478: HTTrace("Net Manager. %d active sockets, decreasing persistent sockets to %d\n",
479: Active, Persistent);
2.23 frystyk 480: }
2.17 frystyk 481:
2.74 frystyk 482: PUBLIC int HTNet_availablePersistentSockets (void)
2.28 frystyk 483: {
2.74 frystyk 484: int available = MaxActive - 2 - Persistent;
485: return available > 0 ? available : 0;
2.28 frystyk 486: }
487:
2.74 frystyk 488: /*
489: ** Returns whether there are any Net objects pending or active
2.40 frystyk 490: */
2.74 frystyk 491: PUBLIC BOOL HTNet_isIdle (void)
2.40 frystyk 492: {
2.74 frystyk 493: return (HTNetCount > 0);
2.40 frystyk 494: }
495:
2.74 frystyk 496: PUBLIC BOOL HTNet_isEmpty (void)
2.1 frystyk 497: {
2.74 frystyk 498: return (HTNetCount <= 0);
2.1 frystyk 499: }
500:
2.81 frystyk 501: PUBLIC int HTNet_count (void)
502: {
503: return HTNetCount;
504: }
505:
2.23 frystyk 506: /* ------------------------------------------------------------------------- */
507: /* Creation and deletion methods */
508: /* ------------------------------------------------------------------------- */
509:
2.99 frystyk 510: PRIVATE int AfterFilterEvent (HTTimer * timer, void * param, HTEventType type)
511: {
512: HTFilterEvent * fe = (HTFilterEvent *) param;
513: if (fe) {
514: HTRequest * request = fe->request;
515: int status = fe->status;
516: if (timer != fe->timer)
517: HTDebugBreak(__FILE__, __LINE__, "Net timer. %p not in sync\n", timer);
518: if (CORE_TRACE)
519: HTTrace("HTNet....... Continuing calling AFTER filters %p with timer %p\n",
520: fe, timer);
521:
522: /* Delete the event context */
523: HT_FREE(fe);
524:
525: /* Now call the remaining AFTER filters */
526: return HTNet_executeAfterAll(request, status);
527: }
528: return HT_ERROR;
529: }
530:
531: PRIVATE BOOL createAfterFilterEvent (HTRequest * request, int status)
532: {
533: HTFilterEvent * me = NULL;
534: if ((me = (HTFilterEvent *) HT_CALLOC(1, sizeof(HTFilterEvent))) == NULL)
535: HT_OUTOFMEM("createAfterFilterEvent");
536: me->request = request;
537: me->status = status;
538: me->timer = HTTimer_new(NULL, AfterFilterEvent, me, 1, YES, NO);
539: return YES;
540: }
541:
2.74 frystyk 542: PRIVATE HTNet * create_object (void)
543: {
544: static int net_hash = 0;
545: HTNet * me = NULL;
546:
547: /* Create new object */
548: if ((me = (HTNet *) HT_CALLOC(1, sizeof(HTNet))) == NULL)
549: HT_OUTOFMEM("HTNet_new");
2.100 ! frystyk 550: me->hash = net_hash++ % HT_XL_HASH_SIZE;
2.74 frystyk 551:
552: /* Insert into hash table */
553: if (!NetTable) {
2.100 ! frystyk 554: if ((NetTable = (HTList **) HT_CALLOC(HT_XL_HASH_SIZE, sizeof(HTList *))) == NULL)
2.74 frystyk 555: HT_OUTOFMEM("create_object");
556: }
557: if (!NetTable[me->hash]) NetTable[me->hash] = HTList_new();
558: HTList_addObject(NetTable[me->hash], (void *) me);
559: HTNetCount++;
560: if (CORE_TRACE)
561: HTTrace("Net Object.. %p created with hash %d\n",me, me->hash);
562: return me;
563: }
564:
2.27 frystyk 565: /* HTNet_duplicate
566: ** ---------------
567: ** Creates a new HTNet object as a duplicate of the same request.
568: ** Returns YES if OK, else NO
569: ** BUG: We do not check if we have a socket free!
570: */
2.43 frystyk 571: PUBLIC HTNet * HTNet_dup (HTNet * src)
2.27 frystyk 572: {
2.74 frystyk 573: if (src) {
574: HTNet * me;
2.75 frystyk 575: int hash;
2.74 frystyk 576: if ((me = create_object()) == NULL) return NULL;
2.75 frystyk 577: hash = me->hash;
2.74 frystyk 578: if (CORE_TRACE) HTTrace("Net Object.. Duplicated %p\n", src);
579: memcpy((void *) me, src, sizeof(HTNet));
2.75 frystyk 580: me->hash = hash; /* Carry over hash entry */
2.74 frystyk 581: return me;
582: }
583: return NULL;
2.27 frystyk 584: }
585:
2.81 frystyk 586: PUBLIC BOOL HTNet_execute (HTNet * net, HTEventType type)
587: {
588: if (net && net->event.cbf && net->request) {
589: if (CORE_TRACE)
2.82 frystyk 590: HTTrace("Net Object.. %p calling %p with event type %d and context %p\n",
591: net, net->event.cbf, type, net->event.param);
592: (*(net->event.cbf))(HTNet_socket(net), net->event.param, type);
2.81 frystyk 593: return YES;
594: }
595: return NO;
596: }
597:
2.74 frystyk 598: /*
599: ** Start a Net obejct by calling the protocol module.
2.30 frystyk 600: */
2.74 frystyk 601: PUBLIC BOOL HTNet_start (HTNet * net)
2.30 frystyk 602: {
2.81 frystyk 603: if (net && net->event.cbf && net->request) {
2.74 frystyk 604: if (CORE_TRACE) HTTrace("Net Object.. Launching %p\n", net);
2.81 frystyk 605: (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_BEGIN);
2.30 frystyk 606: return YES;
607: }
608: return NO;
609: }
610:
2.37 frystyk 611: /* HTNet_new
612: ** ---------
613: ** This function creates a new HTNet object and assigns the socket number
614: ** to it. This is intended to be used when you are going to listen on a
615: ** socket using the HTDoListen() function in HTTCP.c. The function do NOT
616: ** call any of the callback functions.
617: ** Returns new object or NULL on error
618: */
2.81 frystyk 619: PUBLIC HTNet * HTNet_new (HTRequest * request)
2.37 frystyk 620: {
2.81 frystyk 621: HTNet * me;
622: if ((me = create_object()) == NULL) return NULL;
623: me->preemptive = HTRequest_preemptive(request);
624: HTNet_setEventPriority(me, HTRequest_priority(request));
625: me->request = request;
626: HTRequest_setNet(request, me);
627: return me;
2.37 frystyk 628: }
629:
2.67 frystyk 630: /* HTNet_newServer
631: ** ---------------
632: ** Create a new HTNet object as a new request to be handled. If we have
2.74 frystyk 633: ** more than MaxActive connections already then return NO.
2.67 frystyk 634: ** Returns YES if OK, else NO
2.37 frystyk 635: */
2.98 frystyk 636: PUBLIC BOOL HTNet_newServer (HTRequest * request)
2.37 frystyk 637: {
2.98 frystyk 638: HTParentAnchor * anchor = HTRequest_anchor(request);
639: HTNet * me = NULL;
2.37 frystyk 640: HTProtocol * protocol;
2.67 frystyk 641: HTTransport * tp = NULL; /* added JTD:5/28/96 */
2.98 frystyk 642: char * physical = NULL;
643: int status;
2.81 frystyk 644: HTProtCallback * cbf;
2.98 frystyk 645:
2.37 frystyk 646: if (!request) return NO;
647:
2.98 frystyk 648: /*
649: ** First we do all the "BEFORE" callbacks in order to see if we are to
650: ** continue with this request or not. If we receive a callback status
651: ** that is NOT HT_OK then jump directly to the after callbacks and return
652: */
653: if ((status = HTNet_executeBeforeAll(request)) != HT_OK) {
2.99 frystyk 654:
655: /*
656: ** If in non-blocking mode then return here and call AFTER
657: ** filters from a timer event handler. As Olga Antropova
658: ** points out, otherwise, the stack can grow if new requests
659: ** are started directly from the after filters
660: */
661: if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request))
662: createAfterFilterEvent(request, status);
663: else
664: HTNet_executeAfterAll(request, status);
2.98 frystyk 665: return YES;
666: }
667:
668: /*
669: ** If no translation was provided by the filters then use the anchor
670: ** address directly
671: */
672: if (!(physical = HTAnchor_physical(anchor))) {
673: char * addr = HTAnchor_address((HTAnchor *) anchor);
674: if (CORE_TRACE) HTTrace("Net Object.. Using default address\n");
675: HTAnchor_setPhysical(anchor, addr);
676: physical = HTAnchor_physical(anchor);
677: HT_FREE(addr);
678: }
679:
2.37 frystyk 680: /* Find a protocol object for this access scheme */
2.98 frystyk 681: {
682: char * access = HTParse(physical, "", PARSE_ACCESS);
683: if ((protocol = HTProtocol_find(request, access)) == NULL) {
684: if (CORE_TRACE) HTTrace("Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n", access);
685: HT_FREE(access);
686: return NO;
687: }
688: if (!(cbf = HTProtocol_server(protocol))) {
689: if (CORE_TRACE) HTTrace("Net Object.. NO SERVER HANDLER for URI scheme `%s\'\n", access);
690: HT_FREE(access);
691: HT_FREE(me);
692: return NO;
693: }
694: HT_FREE(access);
695: }
2.67 frystyk 696:
697: /* Find a transport object for this protocol */
2.98 frystyk 698: if ((tp = HTTransport_find(request, HTProtocol_transport(protocol))) == NULL) {
699: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT found for protocol `%s\'\n", HTProtocol_name(protocol));
2.67 frystyk 700: return NO;
701: }
702:
2.98 frystyk 703: /* Create new net object and bind to request object */
704: if ((me = create_object()) == NULL) return NO;
705: me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
706: HTNet_setEventPriority(me, HTRequest_priority(request));
707: me->protocol = protocol;
708: me->transport = tp; /* added - JTD:5/28/96 */
709: me->request = request;
710: HTRequest_setNet(request, me);
2.37 frystyk 711:
712: /* Start the server request */
2.58 hallam 713: if (CORE_TRACE)
2.98 frystyk 714: HTTrace("Net Object.. starting SERVER request %p and net object %p\n", request, me);
715: (*(cbf))(INVSOC, request);
2.37 frystyk 716: return YES;
717: }
2.36 frystyk 718:
2.30 frystyk 719: /* HTNet_new
720: ** ---------
2.23 frystyk 721: ** Create a new HTNet object as a new request to be handled. If we have
2.74 frystyk 722: ** more than MaxActive connections already then put this into the
2.23 frystyk 723: ** pending queue, else start the request by calling the call back
724: ** function registered with this access method.
725: ** Returns YES if OK, else NO
726: */
2.37 frystyk 727: PUBLIC BOOL HTNet_newClient (HTRequest * request)
2.23 frystyk 728: {
2.74 frystyk 729: HTParentAnchor * anchor = HTRequest_anchor(request);
2.59 frystyk 730: HTNet * me = NULL;
731: HTProtocol * protocol = NULL;
732: HTTransport * tp = NULL;
2.37 frystyk 733: char * physical = NULL;
2.74 frystyk 734: int status;
2.81 frystyk 735: HTProtCallback * cbf;
736:
2.27 frystyk 737: if (!request) return NO;
2.98 frystyk 738:
2.33 frystyk 739: /*
740: ** First we do all the "BEFORE" callbacks in order to see if we are to
741: ** continue with this request or not. If we receive a callback status
742: ** that is NOT HT_OK then jump directly to the after callbacks and return
743: */
2.79 frystyk 744: if ((status = HTNet_executeBeforeAll(request)) != HT_OK) {
2.99 frystyk 745:
746: /*
747: ** If in non-blocking mode then return here and call AFTER
748: ** filters from a timer event handler. As Olga Antropova
749: ** points out, otherwise, the stack can grow if new requests
750: ** are started directly from the after filters
751: */
752: if (HTEvent_isCallbacksRegistered() && !HTRequest_preemptive(request))
753: createAfterFilterEvent(request, status);
754: else
755: HTNet_executeAfterAll(request, status);
2.33 frystyk 756: return YES;
757: }
758:
2.36 frystyk 759: /*
2.79 frystyk 760: ** If no translation was provided by the filters then use the anchor
2.36 frystyk 761: ** address directly
762: */
2.74 frystyk 763: if (!(physical = HTAnchor_physical(anchor))) {
764: char * addr = HTAnchor_address((HTAnchor *) anchor);
765: if (CORE_TRACE) HTTrace("Net Object.. Using default address\n");
766: HTAnchor_setPhysical(anchor, addr);
767: physical = HTAnchor_physical(anchor);
2.49 frystyk 768: HT_FREE(addr);
2.33 frystyk 769: }
770:
2.37 frystyk 771: /* Find a protocol object for this access scheme */
772: {
2.81 frystyk 773: char * proxy = HTRequest_proxy(request);
774: char * access = HTParse(proxy ? proxy : physical, "", PARSE_ACCESS);
2.37 frystyk 775: if ((protocol = HTProtocol_find(request, access)) == NULL) {
2.98 frystyk 776: if (CORE_TRACE) HTTrace("Net Object.. NO PROTOCOL Object found for URI scheme `%s\'\n", access);
2.49 frystyk 777: HT_FREE(access);
2.37 frystyk 778: return NO;
779: }
2.98 frystyk 780: if (!(cbf = HTProtocol_client(protocol))) {
781: if (CORE_TRACE) HTTrace("Net Object.. NO CLIENT HANDLER for URI scheme `%s\'\n", access);
782: HT_FREE(access);
783: HT_FREE(me);
784: return NO;
785: }
2.49 frystyk 786: HT_FREE(access);
2.37 frystyk 787: }
2.59 frystyk 788:
789: /* Find a transport object for this protocol */
790: tp = HTTransport_find(request, HTProtocol_transport(protocol));
791: if (tp == NULL) {
2.98 frystyk 792: if (CORE_TRACE) HTTrace("Net Object.. NO TRANSPORT found for protocol `%s\'\n", HTProtocol_name(protocol));
2.59 frystyk 793: return NO;
794: }
795:
2.23 frystyk 796: /* Create new net object and bind it to the request object */
2.69 frystyk 797: if ((me = create_object()) == NULL) return NO;
2.74 frystyk 798: me->preemptive = (HTProtocol_preemptive(protocol) || HTRequest_preemptive(request));
2.81 frystyk 799: #if 0
2.69 frystyk 800: me->priority = HTRequest_priority(request);
2.81 frystyk 801: #endif
802: HTNet_setEventPriority(me, HTRequest_priority(request));
2.59 frystyk 803: me->protocol = protocol;
804: me->transport = tp;
2.69 frystyk 805: me->request = request;
806: HTRequest_setNet(request, me);
2.74 frystyk 807:
808: /* Increase the number of retrys for this download */
809: HTRequest_addRetry(request);
2.23 frystyk 810:
811: /*
812: ** Check if we can start the request, else put it into pending queue
813: ** If so then call the call back function associated with the anchor.
814: ** We use the INVSOC as we don't have a valid socket yet!
815: */
2.74 frystyk 816: if (CORE_TRACE)
817: HTTrace("Net Object.. starting request %p (retry=%d) with net object %p\n",
818: request, HTRequest_retrys(request), me);
2.81 frystyk 819: (*(cbf))(INVSOC, request);
2.36 frystyk 820: return YES;
821: }
822:
2.23 frystyk 823: /* delete_object
824: ** -------------
825: ** Deletes an HTNet object
2.40 frystyk 826: ** Return YES if OK, else NO
2.15 frystyk 827: */
2.81 frystyk 828: PRIVATE BOOL delete_object (HTNet * net)
2.15 frystyk 829: {
2.74 frystyk 830: if (CORE_TRACE) HTTrace("Net Object.. Remove object %p\n", net);
2.23 frystyk 831: if (net) {
832:
833: /* Close socket */
2.74 frystyk 834: /*
835: ** As we may have a socket available we check for whether
836: ** we can start any pending requests. We do this by asking for
837: ** pending Host objects. If none then use the current object
838: */
2.81 frystyk 839: /* (*net->input->isa->consumed)(net->input, net->header_length + net->bytes_read);
840: */
2.74 frystyk 841:
2.89 frystyk 842: HTHost_launchPending(net->host);
843:
844: /*
2.74 frystyk 845: ** Break the link to the request and free the Net object
846: */
847: HTRequest_setNet(net->request, NULL);
2.49 frystyk 848: HT_FREE(net);
2.81 frystyk 849: return YES;
850: }
851: return NO;
852: }
853:
854: PRIVATE BOOL remove_net (HTNet * net)
855: {
856: if (net && NetTable) {
857: HTList * list = NetTable[net->hash];
858: if (list) {
859: HTList_removeObject(list, (void *) net);
860: delete_object(net);
861: HTNetCount--;
862: return YES;
863: }
2.23 frystyk 864: }
865: return NO;
866: }
867:
2.74 frystyk 868: /*
869: ** Clears the contents of the Net object so that we can use it again.
870: */
871: PUBLIC BOOL HTNet_clear (HTNet * net)
872: {
873: if (net) {
2.81 frystyk 874: net->host->channel = NULL;
875: net->readStream = NULL;
876: net->bytesRead = 0;
2.95 frystyk 877: net->headerBytesRead = 0;
2.81 frystyk 878: net->bytesWritten = 0;
2.95 frystyk 879: net->headerBytesWritten = 0;
2.74 frystyk 880: return YES;
881: }
882: return NO;
883: }
884:
2.23 frystyk 885: /* HTNet_delete
886: ** ------------
887: ** Deletes the HTNet object from the list of active requests and calls
888: ** any registered call back functions IF not the status is HT_IGNORE.
889: ** This is used if we have internal requests that the app doesn't know
890: ** about. We also see if we have pending requests that can be started
891: ** up now when we have a socket free.
892: ** The callback functions are called in the reverse order of which they
893: ** were registered (last one first)
2.40 frystyk 894: ** Return YES if OK, else NO
2.23 frystyk 895: */
896: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
897: {
2.58 hallam 898: if (CORE_TRACE)
2.74 frystyk 899: HTTrace("Net Object.. Delete %p and call AFTER filters\n", net);
900: if (net) {
901: HTRequest * request = net->request;
2.23 frystyk 902:
2.25 frystyk 903: /*
2.74 frystyk 904: ** If we have a premature close then recover the request. Otherwise
905: ** break the link to the Host object and continue deleting the net
906: ** object
2.25 frystyk 907: */
2.74 frystyk 908: if (net->host) {
2.81 frystyk 909: HTHost_unregister (net->host, net, HTEvent_READ);
910: HTHost_unregister (net->host, net, HTEvent_WRITE);
2.74 frystyk 911: if (status == HT_RECOVER_PIPE) {
912: HTNet_clear(net);
2.58 hallam 913: if (CORE_TRACE)
2.74 frystyk 914: HTTrace("Net Object.. Restarting request %p (retry=%d) with net object %p\n",
915: request, HTRequest_retrys(request), net);
916: return YES;
2.81 frystyk 917: }
2.97 frystyk 918: HTHost_deleteNet(net->host, net, status);
2.92 frystyk 919: if (HTHost_doRecover(net->host)) HTHost_recoverPipe(net->host);
2.89 frystyk 920: }
2.74 frystyk 921:
922: /* Remove object from the table of Net Objects */
2.81 frystyk 923: remove_net(net);
2.82 frystyk 924:
2.74 frystyk 925: /* Call AFTER filters */
2.79 frystyk 926: HTNet_executeAfterAll(request, status);
2.74 frystyk 927: return YES;
2.23 frystyk 928: }
929: return NO;
2.98 frystyk 930: }
931:
932: PUBLIC BOOL HTNet_deleteDup (HTNet * dup)
933: {
934: return dup ? remove_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.58 hallam 944: if (CORE_TRACE)
2.74 frystyk 945: HTTrace("Net Object.. Remove all Net objects, NO filters\n");
946: if (NetTable) {
947: HTList * cur = NULL;
948: HTNet * pres = NULL;
949: int cnt;
2.100 ! frystyk 950: for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {
2.74 frystyk 951: if ((cur = NetTable[cnt])) {
952: while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL)
2.81 frystyk 953: delete_object(pres);
2.74 frystyk 954: }
955: HTList_delete(NetTable[cnt]);
2.25 frystyk 956: }
2.74 frystyk 957: HT_FREE(NetTable);
958: HTNetCount = 0;
959: return YES;
2.25 frystyk 960: }
961: return NO;
2.97 frystyk 962: }
963:
964: /*
965: ** When pipelining, it is not possible to kill a single request
966: ** as we then loose track of where we are in the pipe. It is
967: ** therefore necessary to kill the whole pipeline.
968: */
969: PUBLIC BOOL HTNet_killPipe (HTNet * net)
970: {
971: return (net && net->host) ? HTHost_killPipe(net->host) : NO;
2.25 frystyk 972: }
973:
2.23 frystyk 974: /* HTNet_kill
975: ** ----------
976: ** Kill the request by calling the call back function with a request for
977: ** closing the connection. Does not remove the object. This is done by
978: ** HTNet_delete() function which is called by the load routine.
979: ** Returns OK if success, NO on error
980: */
2.74 frystyk 981: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23 frystyk 982: {
2.81 frystyk 983: if (net) {
2.94 frystyk 984: HTAlertCallback * cbf = HTAlert_find(HT_PROG_INTERRUPT);
985: if (cbf) (*cbf)(net->request, HT_PROG_INTERRUPT, HT_MSG_NULL, NULL, NULL, NULL);
2.81 frystyk 986: if (CORE_TRACE) HTTrace("Net Object.. Killing %p\n", net);
987: if (net->event.cbf) {
988: (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_CLOSE);
989: return YES;
990: }
991: return remove_net(net);
2.23 frystyk 992: }
2.81 frystyk 993: if (CORE_TRACE) HTTrace("Net Object.. No object to kill\n");
2.23 frystyk 994: return NO;
995: }
996:
997: /* HTNet_killAll
998: ** -------------
2.74 frystyk 999: ** Kills all registered net objects by calling the call
2.23 frystyk 1000: ** back function with a request for closing the connection. We do not
1001: ** remove the HTNet object as it is done by HTNet_delete().
1002: ** Returns OK if success, NO on error
1003: */
1004: PUBLIC BOOL HTNet_killAll (void)
1005: {
2.74 frystyk 1006: if (CORE_TRACE) HTTrace("Net Object.. Kill ALL Net objects!!!\n");
1007: if (NetTable) {
1008: HTList * cur = NULL;
1009: HTNet * pres = NULL;
1010: int cnt;
2.100 ! frystyk 1011: for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {
2.74 frystyk 1012: if ((cur = NetTable[cnt])) {
2.75 frystyk 1013: while ((pres = (HTNet *) HTList_lastObject(cur)) != NULL)
2.74 frystyk 1014: HTNet_kill(pres);
1015: }
2.25 frystyk 1016: }
2.74 frystyk 1017: return YES;
2.25 frystyk 1018: }
2.74 frystyk 1019: if (CORE_TRACE) HTTrace("Net Object.. No objects to kill\n");
1020: return NO;
2.23 frystyk 1021: }
2.38 frystyk 1022:
1023: /* ------------------------------------------------------------------------- */
2.59 frystyk 1024: /* Connection Specifics */
1025: /* ------------------------------------------------------------------------- */
1026:
2.74 frystyk 1027: /* HTNet_priority
1028: ** --------------
1029: ** Get the current priority of the Net object
1030: */
1031: PUBLIC HTPriority HTNet_priority (HTNet * net)
1032: {
2.81 frystyk 1033: return (net ? net->event.priority : HT_PRIORITY_INV);
2.74 frystyk 1034: }
1035:
1036: /* HTNet_setPriority
1037: ** -----------------
1038: ** Set the current priority of the Net object
1039: ** This will change the priority next time the thread is blocked
1040: */
1041: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
1042: {
1043: if (net) {
2.81 frystyk 1044: net->event.priority = priority;
2.74 frystyk 1045: return YES;
1046: }
1047: return NO;
1048: }
1049:
2.59 frystyk 1050: /* HTNet_Persistent
1051: ** ----------------
1052: ** Check whether the net object handles persistent connections
1053: ** If we have a DNS entry then check that as well.
1054: */
1055: PUBLIC BOOL HTNet_persistent (HTNet * net)
1056: {
1057: return (net && HTHost_isPersistent(net->host));
1058: }
1059:
1060: /* HTNet_persistent
1061: ** ----------------
1062: ** Set the net object to handle persistent connections
1063: ** If we also have a DNS entry then update that as well
1064: */
2.74 frystyk 1065: PUBLIC BOOL HTNet_setPersistent (HTNet * net,
1066: BOOL persistent,
1067: HTTransportMode mode)
2.59 frystyk 1068: {
1069: if (net) {
2.81 frystyk 1070: BOOL result = HTHost_setPersistent(net->host, persistent, mode);
2.74 frystyk 1071: if (CORE_TRACE)
1072: HTTrace("Net Object.. Persistent connection set %s %s\n",
1073: persistent ? "ON" : "OFF",
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.81 frystyk 1224: if (CORE_TRACE) HTTrace("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