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