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