Annotation of libwww/Library/src/HTNet.c, revision 2.102
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.102 ! frystyk 6: ** @(#) $Id: HTNet.c,v 2.101 1999/02/09 23:11:32 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.101 frystyk 823: /*
824: ** Check whether we have any pending HTNet objects and if so
825: ** then start the next one.
2.40 frystyk 826: ** Return YES if OK, else NO
2.15 frystyk 827: */
2.101 frystyk 828: PRIVATE BOOL check_pending (HTNet * net)
2.15 frystyk 829: {
2.101 frystyk 830: if (CORE_TRACE) HTTrace("Net Object.. Check for pending Net objects\n");
2.23 frystyk 831: if (net) {
832:
2.74 frystyk 833: /*
834: ** As we may have a socket available we check for whether
835: ** we can start any pending requests. We do this by asking for
836: ** pending Host objects. If none then use the current object
837: */
2.101 frystyk 838: HTHost_launchPending(net->host);
2.74 frystyk 839:
2.101 frystyk 840: return YES;
841: }
842: return NO;
843: }
2.89 frystyk 844:
2.101 frystyk 845: PRIVATE BOOL free_net (HTNet * net)
846: {
847: if (CORE_TRACE) HTTrace("Net Object.. Freeing object %p\n", net);
848: if (net) {
849: HTRequest_setNet(net->request, NULL);
850: HT_FREE(net);
2.81 frystyk 851: return YES;
852: }
853: return NO;
854: }
855:
2.101 frystyk 856: /*
857: ** Unregister the net object from the global list
858: ** and see if we can start a new pending request.
859: */
860: PRIVATE BOOL unregister_net (HTNet * net)
2.81 frystyk 861: {
862: if (net && NetTable) {
863: HTList * list = NetTable[net->hash];
864: if (list) {
865: HTList_removeObject(list, (void *) net);
2.101 frystyk 866: check_pending(net);
2.81 frystyk 867: HTNetCount--;
868: return YES;
869: }
2.23 frystyk 870: }
871: return NO;
872: }
873:
2.74 frystyk 874: /*
875: ** Clears the contents of the Net object so that we can use it again.
876: */
877: PUBLIC BOOL HTNet_clear (HTNet * net)
878: {
879: if (net) {
2.81 frystyk 880: net->host->channel = NULL;
881: net->readStream = NULL;
882: net->bytesRead = 0;
2.95 frystyk 883: net->headerBytesRead = 0;
2.81 frystyk 884: net->bytesWritten = 0;
2.95 frystyk 885: net->headerBytesWritten = 0;
2.74 frystyk 886: return YES;
887: }
888: return NO;
889: }
890:
2.23 frystyk 891: /* HTNet_delete
892: ** ------------
893: ** Deletes the HTNet object from the list of active requests and calls
894: ** any registered call back functions IF not the status is HT_IGNORE.
895: ** This is used if we have internal requests that the app doesn't know
896: ** about. We also see if we have pending requests that can be started
897: ** up now when we have a socket free.
898: ** The callback functions are called in the reverse order of which they
899: ** were registered (last one first)
2.40 frystyk 900: ** Return YES if OK, else NO
2.23 frystyk 901: */
902: PUBLIC BOOL HTNet_delete (HTNet * net, int status)
903: {
2.58 hallam 904: if (CORE_TRACE)
2.74 frystyk 905: HTTrace("Net Object.. Delete %p and call AFTER filters\n", net);
906: if (net) {
907: HTRequest * request = net->request;
2.23 frystyk 908:
2.25 frystyk 909: /*
2.74 frystyk 910: ** If we have a premature close then recover the request. Otherwise
911: ** break the link to the Host object and continue deleting the net
912: ** object
2.25 frystyk 913: */
2.74 frystyk 914: if (net->host) {
2.81 frystyk 915: HTHost_unregister (net->host, net, HTEvent_READ);
916: HTHost_unregister (net->host, net, HTEvent_WRITE);
2.74 frystyk 917: if (status == HT_RECOVER_PIPE) {
918: HTNet_clear(net);
2.58 hallam 919: if (CORE_TRACE)
2.74 frystyk 920: HTTrace("Net Object.. Restarting request %p (retry=%d) with net object %p\n",
921: request, HTRequest_retrys(request), net);
922: return YES;
2.81 frystyk 923: }
2.97 frystyk 924: HTHost_deleteNet(net->host, net, status);
2.92 frystyk 925: if (HTHost_doRecover(net->host)) HTHost_recoverPipe(net->host);
2.89 frystyk 926: }
2.74 frystyk 927:
928: /* Remove object from the table of Net Objects */
2.101 frystyk 929: unregister_net(net);
2.102 ! frystyk 930: free_net(net);
2.82 frystyk 931:
2.74 frystyk 932: /* Call AFTER filters */
2.79 frystyk 933: HTNet_executeAfterAll(request, status);
2.101 frystyk 934:
935: /*
936: ** Truely delete the HTNet object. Thanks to Mikhail Grouchinski
937: ** we now do this after having called the after filters so that
938: ** these filters can use the information in the Net object
939: */
940:
941: return YES;
2.23 frystyk 942: }
943: return NO;
2.98 frystyk 944: }
945:
946: PUBLIC BOOL HTNet_deleteDup (HTNet * dup)
947: {
2.101 frystyk 948: return dup ? (unregister_net(dup) && free_net(dup)) : NO;
2.23 frystyk 949: }
950:
951: /* HTNet_deleteAll
952: ** ---------------
953: ** Deletes all HTNet object that might either be active or pending
2.74 frystyk 954: ** We DO NOT call the AFTER filters - A crude way of saying goodbye!
2.23 frystyk 955: */
956: PUBLIC BOOL HTNet_deleteAll (void)
957: {
2.58 hallam 958: if (CORE_TRACE)
2.74 frystyk 959: HTTrace("Net Object.. Remove all Net objects, NO filters\n");
960: if (NetTable) {
961: HTList * cur = NULL;
962: HTNet * pres = NULL;
963: int cnt;
2.100 frystyk 964: for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {
2.74 frystyk 965: if ((cur = NetTable[cnt])) {
2.101 frystyk 966: while ((pres = (HTNet *) HTList_nextObject(cur)) != NULL) {
967: check_pending(pres);
968: free_net(pres);
969: }
2.74 frystyk 970: }
971: HTList_delete(NetTable[cnt]);
2.25 frystyk 972: }
2.74 frystyk 973: HT_FREE(NetTable);
974: HTNetCount = 0;
975: return YES;
2.25 frystyk 976: }
977: return NO;
2.97 frystyk 978: }
979:
980: /*
981: ** When pipelining, it is not possible to kill a single request
982: ** as we then loose track of where we are in the pipe. It is
983: ** therefore necessary to kill the whole pipeline.
984: */
985: PUBLIC BOOL HTNet_killPipe (HTNet * net)
986: {
987: return (net && net->host) ? HTHost_killPipe(net->host) : NO;
2.25 frystyk 988: }
989:
2.23 frystyk 990: /* HTNet_kill
991: ** ----------
992: ** Kill the request by calling the call back function with a request for
993: ** closing the connection. Does not remove the object. This is done by
994: ** HTNet_delete() function which is called by the load routine.
995: ** Returns OK if success, NO on error
996: */
2.74 frystyk 997: PUBLIC BOOL HTNet_kill (HTNet * net)
2.23 frystyk 998: {
2.81 frystyk 999: if (net) {
2.94 frystyk 1000: HTAlertCallback * cbf = HTAlert_find(HT_PROG_INTERRUPT);
1001: if (cbf) (*cbf)(net->request, HT_PROG_INTERRUPT, HT_MSG_NULL, NULL, NULL, NULL);
2.81 frystyk 1002: if (CORE_TRACE) HTTrace("Net Object.. Killing %p\n", net);
1003: if (net->event.cbf) {
1004: (*(net->event.cbf))(HTNet_socket(net), net->event.param, HTEvent_CLOSE);
1005: return YES;
1006: }
2.101 frystyk 1007: return unregister_net(net) && free_net(net);
2.23 frystyk 1008: }
2.81 frystyk 1009: if (CORE_TRACE) HTTrace("Net Object.. No object to kill\n");
2.23 frystyk 1010: return NO;
1011: }
1012:
1013: /* HTNet_killAll
1014: ** -------------
2.74 frystyk 1015: ** Kills all registered net objects by calling the call
2.23 frystyk 1016: ** back function with a request for closing the connection. We do not
1017: ** remove the HTNet object as it is done by HTNet_delete().
1018: ** Returns OK if success, NO on error
1019: */
1020: PUBLIC BOOL HTNet_killAll (void)
1021: {
2.74 frystyk 1022: if (CORE_TRACE) HTTrace("Net Object.. Kill ALL Net objects!!!\n");
1023: if (NetTable) {
1024: HTList * cur = NULL;
1025: HTNet * pres = NULL;
1026: int cnt;
2.100 frystyk 1027: for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {
2.74 frystyk 1028: if ((cur = NetTable[cnt])) {
2.75 frystyk 1029: while ((pres = (HTNet *) HTList_lastObject(cur)) != NULL)
2.74 frystyk 1030: HTNet_kill(pres);
1031: }
2.25 frystyk 1032: }
2.74 frystyk 1033: return YES;
2.25 frystyk 1034: }
2.74 frystyk 1035: if (CORE_TRACE) HTTrace("Net Object.. No objects to kill\n");
1036: return NO;
2.23 frystyk 1037: }
2.38 frystyk 1038:
1039: /* ------------------------------------------------------------------------- */
2.59 frystyk 1040: /* Connection Specifics */
1041: /* ------------------------------------------------------------------------- */
1042:
2.74 frystyk 1043: /* HTNet_priority
1044: ** --------------
1045: ** Get the current priority of the Net object
1046: */
1047: PUBLIC HTPriority HTNet_priority (HTNet * net)
1048: {
2.81 frystyk 1049: return (net ? net->event.priority : HT_PRIORITY_INV);
2.74 frystyk 1050: }
1051:
1052: /* HTNet_setPriority
1053: ** -----------------
1054: ** Set the current priority of the Net object
1055: ** This will change the priority next time the thread is blocked
1056: */
1057: PUBLIC BOOL HTNet_setPriority (HTNet * net, HTPriority priority)
1058: {
1059: if (net) {
2.81 frystyk 1060: net->event.priority = priority;
2.74 frystyk 1061: return YES;
1062: }
1063: return NO;
1064: }
1065:
2.59 frystyk 1066: /* HTNet_Persistent
1067: ** ----------------
1068: ** Check whether the net object handles persistent connections
1069: ** If we have a DNS entry then check that as well.
1070: */
1071: PUBLIC BOOL HTNet_persistent (HTNet * net)
1072: {
1073: return (net && HTHost_isPersistent(net->host));
1074: }
1075:
1076: /* HTNet_persistent
1077: ** ----------------
1078: ** Set the net object to handle persistent connections
1079: ** If we also have a DNS entry then update that as well
1080: */
2.74 frystyk 1081: PUBLIC BOOL HTNet_setPersistent (HTNet * net,
1082: BOOL persistent,
1083: HTTransportMode mode)
2.59 frystyk 1084: {
1085: if (net) {
2.81 frystyk 1086: BOOL result = HTHost_setPersistent(net->host, persistent, mode);
2.74 frystyk 1087: if (CORE_TRACE)
1088: HTTrace("Net Object.. Persistent connection set %s %s\n",
1089: persistent ? "ON" : "OFF",
1090: result ? "succeeded" : "failed");
2.81 frystyk 1091: return result;
2.59 frystyk 1092: }
1093: return NO;
1094: }
1095:
2.66 frystyk 1096: /*
1097: ** Context pointer to be used in context call back function
1098: */
1099: PUBLIC BOOL HTNet_setContext (HTNet * net, void * context)
1100: {
1101: if (net) {
1102: net->context = context;
1103: return YES;
1104: }
1105: return NO;
1106: }
1107:
1108: PUBLIC void * HTNet_context (HTNet * net)
1109: {
1110: return net ? net->context : NULL;
1111: }
2.38 frystyk 1112:
1113: /*
2.60 frystyk 1114: ** Get and set the socket number
1115: */
1116: PUBLIC BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd)
1117: {
2.81 frystyk 1118: if (net && net->host && net->host->channel) {
1119: HTChannel_setSocket(net->host->channel, sockfd);
2.60 frystyk 1120: return YES;
1121: }
1122: return NO;
1123: }
1124:
1125: PUBLIC SOCKET HTNet_socket (HTNet * net)
1126: {
2.81 frystyk 1127: return (net && net->host && net->host->channel ? HTChannel_socket(net->host->channel) : INVSOC);
2.69 frystyk 1128: }
1129:
1130: /*
1131: ** Get and set the HTRequest object
1132: */
1133: PUBLIC BOOL HTNet_setRequest (HTNet * net, HTRequest * request)
1134: {
1135: if (net && request) {
1136: net->request = request;
1137: return YES;
1138: }
1139: return NO;
1140: }
1141:
1142: PUBLIC HTRequest * HTNet_request (HTNet * net)
1143: {
1144: return (net ? net->request : NULL);
2.60 frystyk 1145: }
1146:
1147: /*
2.59 frystyk 1148: ** Get and set the HTChannel object
2.55 frystyk 1149: */
2.59 frystyk 1150: PUBLIC BOOL HTNet_setChannel (HTNet * net, HTChannel * channel)
2.55 frystyk 1151: {
2.81 frystyk 1152: return (net && channel) ? HTHost_setChannel(net->host, channel) : NO;
2.55 frystyk 1153: }
1154:
2.59 frystyk 1155: PUBLIC HTChannel * HTNet_channel (HTNet * net)
2.55 frystyk 1156: {
2.81 frystyk 1157: return net ? HTHost_channel(net->host) : NULL;
2.59 frystyk 1158: }
1159:
1160: /*
1161: ** Get and set the HTHost object
1162: */
1163: PUBLIC BOOL HTNet_setHost (HTNet * net, HTHost * host)
1164: {
1165: if (net && host) {
1166: net->host = host;
1167: return YES;
1168: }
1169: return NO;
1170: }
1171:
1172: PUBLIC HTHost * HTNet_host (HTNet * net)
1173: {
1174: return (net ? net->host : NULL);
1175: }
1176:
1177: /*
1178: ** Get and set the HTdns object
1179: */
1180: PUBLIC BOOL HTNet_setDns (HTNet * net, HTdns * dns)
1181: {
1182: if (net && dns) {
2.81 frystyk 1183: net->host->dns = dns;
2.59 frystyk 1184: return YES;
1185: }
1186: return NO;
1187: }
1188:
1189: PUBLIC HTdns * HTNet_dns (HTNet * net)
1190: {
2.81 frystyk 1191: return (net ? net->host->dns : NULL);
2.59 frystyk 1192: }
1193:
2.81 frystyk 1194: PUBLIC BOOL HTNet_setProtocol (HTNet * net, HTProtocol * protocol)
1195: {
1196: if (net && protocol) {
1197: net->protocol = protocol;
1198: return YES;
1199: }
1200: return NO;
1201: }
1202:
1203: PUBLIC HTProtocol * HTNet_protocol (HTNet * net)
2.72 frystyk 1204: {
2.81 frystyk 1205: return (net ? net->protocol : NULL);
2.72 frystyk 1206: }
2.59 frystyk 1207:
2.86 frystyk 1208: PUBLIC BOOL HTNet_setTransport (HTNet * net, HTTransport * tp)
1209: {
1210: if (net && tp) {
1211: net->transport = tp;
1212: return YES;
1213: }
1214: return NO;
1215: }
1216:
1217: PUBLIC HTTransport * HTNet_transport (HTNet * net)
1218: {
1219: return (net ? net->transport : NULL);
1220: }
1221:
1222: PUBLIC BOOL HTNet_preemptive (HTNet * net)
1223: {
1224: return (net ? net->preemptive : NO);
1225: }
1226:
2.59 frystyk 1227: /*
1228: ** Create the output stream and bind it to the channel
1229: ** Please read the description in the HTIOStream module on the parameters
1230: */
2.81 frystyk 1231: PUBLIC HTOutputStream * HTNet_getOutput (HTNet * me, void * param, int mode)
2.59 frystyk 1232: {
2.81 frystyk 1233: if (me && me->host && me->host->channel && me->transport) {
1234: HTTransport * tp = me->transport;
1235: HTChannel * ch = me->host->channel;
1236: HTOutputStream * output = (*tp->output_new)(me->host, ch, param, mode);
2.74 frystyk 1237: HTChannel_setOutput(ch, output);
2.59 frystyk 1238: return output;
1239: }
2.81 frystyk 1240: if (CORE_TRACE) HTTrace("Host Object.. Can't create output stream\n");
2.59 frystyk 1241: return NULL;
2.81 frystyk 1242: }
1243:
2.87 frystyk 1244: PUBLIC HTEvent * HTNet_event (HTNet * net)
2.81 frystyk 1245: {
2.87 frystyk 1246: return net ? &net->event : NULL;
1247: }
1248:
1249: PUBLIC BOOL HTNet_setEventParam (HTNet * net, void * eventParam)
1250: {
2.81 frystyk 1251: if (net) return HTEvent_setParam(&net->event, eventParam);
1252: return NO;
1253: }
1254:
2.87 frystyk 1255: PUBLIC void * HTNet_eventParam (HTNet * net)
2.81 frystyk 1256: {
2.87 frystyk 1257: return net ? net->event.param : NULL;
2.81 frystyk 1258: }
1259:
1260: PUBLIC BOOL HTNet_setEventCallback(HTNet * net, HTEventCallback * cbf)
1261: {
1262: if (net) return HTEvent_setCallback(&net->event, cbf);
1263: return NO;
1264: }
1265:
1266: PUBLIC HTEventCallback * HTNet_eventCallback(HTNet * net)
1267: {
1268: return net->event.cbf;
1269: }
1270:
1271: PUBLIC BOOL HTNet_setEventPriority(HTNet * net, HTPriority priority)
1272: {
1273: if (net) return HTEvent_setPriority(&net->event, priority);
1274: return NO;
1275: }
1276:
1277: PUBLIC HTPriority HTNet_eventPriority(HTNet * net)
1278: {
1279: return net->event.priority;
1280: }
1281:
1282: PUBLIC HTStream * HTNet_readStream(HTNet * net)
1283: {
1284: if (!net) return NULL;
1285: return net->readStream;
1286: }
1287:
1288: PUBLIC BOOL HTNet_setReadStream (HTNet * net, HTStream * stream)
1289: {
1290: if (net) {
1291: net->readStream = stream;
1292: return YES;
1293: }
1294: return NO;
2.96 frystyk 1295: }
1296:
1297: /*
1298: ** Should we do raw byte count at the network or later?
1299: ** Normally it is later but in cases like FTP we need it
1300: ** in the raw form
1301: */
1302: PUBLIC BOOL HTNet_setRawBytesCount (HTNet * net, BOOL mode)
1303: {
1304: if (net) {
1305: net->countRawBytes = mode;
1306: return YES;
1307: }
1308: return NO;
1309: }
1310:
1311: PUBLIC BOOL HTNet_rawBytesCount (HTNet * net)
1312: {
1313: return (net && net->countRawBytes);
2.55 frystyk 1314: }
Webmaster