Annotation of libwww/Library/src/HTReqMan.c, revision 2.22.2.1
2.1 frystyk 1: /* HTReqMan.c
2: ** REQUEST MANAGER
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
6: **
7: ** Authors
8: ** TBL Tim Berners-Lee timbl@w3.org
9: ** JFG Jean-Francois Groff jfg@dxcern.cern.ch
10: ** DD Denis DeLaRoca (310) 825-4580 <CSP1DWD@mvs.oac.ucla.edu>
11: ** HFN Henrik Frystyk, frystyk@w3.org
12: ** History
13: ** 8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
14: ** 26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
15: ** 6 Oct 92 Moved HTClientHost and HTlogfile into here. TBL
16: ** 17 Dec 92 Tn3270 added, bug fix. DD
17: ** 4 Feb 93 Access registration, Search escapes bad chars TBL
18: ** PARAMETERS TO HTSEARCH AND HTLOADRELATIVE CHANGED
19: ** 28 May 93 WAIS gateway explicit if no WAIS library linked in.
20: ** Dec 93 Bug change around, more reentrant, etc
21: ** 09 May 94 logfile renamed to HTlogfile to avoid clash with WAIS
22: ** 8 Jul 94 Insulate free() from _free structure element.
23: ** 02 Sep 95 Rewritten and spawned from HTAccess.c, HFN
24: */
25:
26: #if !defined(HT_DIRECT_WAIS) && !defined(HT_DEFAULT_WAIS_GATEWAY)
27: #define HT_DEFAULT_WAIS_GATEWAY "http://www.w3.org:8001/"
28: #endif
29:
30: /* Library include files */
31: #include "tcp.h"
32: #include "HTUtils.h"
33: #include "HTString.h"
34: #include "HTParse.h"
35: #include "HTAlert.h"
36: #include "HTError.h"
37: #include "HTList.h"
38: #include "HTCache.h"
2.2 frystyk 39: #include "HTNetMan.h"
2.1 frystyk 40: #include "HTEvntrg.h"
41: #include "HTProt.h"
42: #include "HTProxy.h"
43: #include "HTReqMan.h" /* Implemented here */
44:
2.14 frystyk 45: #include "HTRules.h"
46:
2.1 frystyk 47: #ifndef HT_MAX_RELOADS
48: #define HT_MAX_RELOADS 6
49: #endif
2.13 frystyk 50:
2.1 frystyk 51: PRIVATE int HTMaxRetry = HT_MAX_RELOADS;
52:
53: struct _HTStream {
54: HTStreamClass * isa;
55: /* ... */
56: };
57:
58: /* --------------------------------------------------------------------------*/
59: /* Management of the HTRequest structure */
60: /* --------------------------------------------------------------------------*/
61:
62: /* Create a request structure
63: ** ---------------------------
64: */
2.3 frystyk 65: PUBLIC HTRequest * HTRequest_new (void)
2.1 frystyk 66: {
67: HTRequest * me = (HTRequest*) calloc(1, sizeof(HTRequest));
68: if (!me) outofmem(__FILE__, "HTRequest_new()");
69:
2.7 frystyk 70: /* Force Reload */
2.1 frystyk 71: me->reload = HT_ANY_VERSION;
72:
73: /* Format of output */
74: me->output_format = WWW_PRESENT; /* default it to present to user */
2.21 frystyk 75: me->debug_format = WWW_DEBUG; /* default format of error messages */
2.1 frystyk 76:
77: /* HTTP headers */
78: me->GenMask = DEFAULT_GENERAL_HEADERS;
79: me->RequestMask = DEFAULT_REQUEST_HEADERS;
2.22 frystyk 80: me->ResponseMask = DEFAULT_RESPONSE_HEADERS;
2.1 frystyk 81: me->EntityMask = DEFAULT_ENTITY_HEADERS;
82:
83: /* Default retry after value */
84: me->retry_after = -1;
2.19 frystyk 85: me->priority = HT_PRIORITY_MAX;
2.1 frystyk 86:
87: /* Content negotiation */
88: me->ContentNegotiation = NO; /* Do this by default */
89:
2.13 frystyk 90: #ifdef WWW_WIN_ASYNC
91: HTEvent_winHandle(me);
2.1 frystyk 92: #endif
93: return me;
94: }
95:
2.18 frystyk 96: /* HTRequest_dup
97: ** -------------
98: ** Creates a new HTRequest object as a duplicate of the src request.
99: ** Returns YES if OK, else NO
100: */
101: PUBLIC HTRequest * HTRequest_dup (HTRequest * src)
102: {
103: HTRequest * me;
104: if (!src) return NO;
2.22 frystyk 105: if ((me = (HTRequest *) malloc(sizeof(HTRequest))) == NULL)
2.18 frystyk 106: outofmem(__FILE__, "HTRequest_dup");
107: memcpy(me, src, sizeof(HTRequest));
108: return me;
109: }
2.1 frystyk 110:
2.22.2.1! frystyk 111: /* HTRequest_dupInternal
! 112: ** ---------------------
! 113: ** Creates a new HTRequest object as a duplicate of the src request.
! 114: ** The difference to the HTRequest_dup function is that we don't copy the
! 115: ** error_stack and other information that the application keeps in its
! 116: ** copy of the request object. Otherwise it will be freed multiple times
! 117: ** Returns YES if OK, else NO
! 118: */
! 119: PUBLIC HTRequest * HTRequest_dupInternal (HTRequest * src)
! 120: {
! 121: HTRequest * me;
! 122: if (!src) return NO;
! 123: if ((me = (HTRequest *) malloc(sizeof(HTRequest))) == NULL)
! 124: outofmem(__FILE__, "HTRequest_dup");
! 125: memcpy(me, src, sizeof(HTRequest));
! 126: me->internal = YES;
! 127: me->boundary = NULL;
! 128: me->authenticate = NULL;
! 129: me->error_stack = NULL;
! 130: me->access = NULL;
! 131: me->authorization = NULL;
! 132: me->prot_template = NULL;
! 133: me->dialog_msg = NULL;
! 134: me->net = NULL;
! 135: me->WWWAAScheme = NULL;
! 136: me->WWWAARealm = NULL;
! 137: me->WWWprotection = NULL;
! 138: return me;
! 139: }
! 140:
2.1 frystyk 141: /* Delete a request structure
142: ** --------------------------
143: */
2.3 frystyk 144: PUBLIC void HTRequest_delete (HTRequest * request)
2.1 frystyk 145: {
146: if (request) {
2.11 frystyk 147: FREE(request->boundary);
2.1 frystyk 148: FREE(request->authenticate);
2.11 frystyk 149: if (request->error_stack) HTError_deleteAll(request->error_stack);
2.13 frystyk 150:
2.18 frystyk 151: FREE(request->access);
152:
2.13 frystyk 153: FREE(request->authorization);
154: FREE(request->prot_template);
155: FREE(request->dialog_msg);
2.1 frystyk 156:
157: if (request->net) /* Break connection to HTNet */
158: request->net->request = NULL;
159:
160: /* These are temporary until we get a MIME thingy */
161: FREE(request->WWWAAScheme);
162: FREE(request->WWWAARealm);
163: FREE(request->WWWprotection);
164:
165: FREE(request);
166: }
167: }
168:
169: /*
170: ** Method
171: */
2.3 frystyk 172: PUBLIC void HTRequest_setMethod (HTRequest *request, HTMethod method)
2.1 frystyk 173: {
174: if (request) request->method = method;
175: }
176:
2.3 frystyk 177: PUBLIC HTMethod HTRequest_method (HTRequest *request)
2.1 frystyk 178: {
179: return request ? request->method : METHOD_INVALID;
180: }
181:
182: /*
183: ** Reload Mode
184: */
2.3 frystyk 185: PUBLIC void HTRequest_setReloadMode (HTRequest *request, HTReload mode)
2.1 frystyk 186: {
187: if (request) request->reload = mode;
188: }
189:
2.3 frystyk 190: PUBLIC HTReload HTRequest_reloadMode (HTRequest *request)
2.1 frystyk 191: {
192: return request ? request->reload : HT_ANY_VERSION;
193: }
194:
195: /*
196: ** Accept Format Types
197: ** list can be NULL
198: */
2.6 frystyk 199: PUBLIC void HTRequest_setConversion (HTRequest *request, HTList *type,
200: BOOL override)
2.1 frystyk 201: {
202: if (request) {
203: request->conversions = type;
204: request->conv_local = override;
205: }
206: }
207:
2.6 frystyk 208: PUBLIC HTList * HTRequest_conversion (HTRequest *request)
2.1 frystyk 209: {
210: return request ? request->conversions : NULL;
211: }
212:
213: /*
214: ** Accept Encoding
215: ** list can be NULL
216: */
2.3 frystyk 217: PUBLIC void HTRequest_setEncoding (HTRequest *request, HTList *enc,
218: BOOL override)
2.1 frystyk 219: {
220: if (request) {
221: request->encodings = enc;
222: request->enc_local = override;
223: }
224: }
225:
2.3 frystyk 226: PUBLIC HTList * HTRequest_encoding (HTRequest *request)
2.1 frystyk 227: {
228: return request ? request->encodings : NULL;
229: }
230:
231: /*
232: ** Accept Language
233: ** list can be NULL
234: */
2.3 frystyk 235: PUBLIC void HTRequest_setLanguage (HTRequest *request, HTList *lang,
236: BOOL override)
2.1 frystyk 237: {
238: if (request) {
239: request->languages = lang;
240: request->lang_local = override;
241: }
242: }
243:
2.3 frystyk 244: PUBLIC HTList * HTRequest_language (HTRequest *request)
2.1 frystyk 245: {
246: return request ? request->languages : NULL;
247: }
248:
249: /*
250: ** Accept Charset
251: ** list can be NULL
252: */
2.3 frystyk 253: PUBLIC void HTRequest_setCharset (HTRequest *request, HTList *charset,
254: BOOL override)
2.1 frystyk 255: {
256: if (request) {
257: request->charsets = charset;
258: request->char_local = override;
259: }
260: }
261:
2.3 frystyk 262: PUBLIC HTList * HTRequest_charset (HTRequest *request)
2.1 frystyk 263: {
264: return request ? request->charsets : NULL;
265: }
266:
267: /*
2.9 frystyk 268: ** Extra Header Generators. list can be NULL
269: */
270: PUBLIC void HTRequest_setGenerator (HTRequest *request, HTList *generator,
271: BOOL override)
272: {
273: if (request) {
274: request->generators = generator;
275: request->gens_local = override;
276: }
277: }
278:
279: PUBLIC HTList * HTRequest_generator (HTRequest *request, BOOL *override)
280: {
281: if (request) {
282: *override = request->gens_local;
283: return request->generators;
284: }
285: return NULL;
286: }
287:
288: /*
289: ** Extra Header Parsers. list can be NULL
290: */
291: PUBLIC void HTRequest_setParser (HTRequest *request, HTList *parser,
292: BOOL override)
293: {
294: if (request) {
295: request->parsers = parser;
296: request->pars_local = override;
297: }
298: }
299:
300: PUBLIC HTList * HTRequest_parser (HTRequest *request, BOOL *override)
301: {
302: if (request) {
303: *override = request->pars_local;
304: return request->parsers;
305: }
306: return NULL;
307: }
308:
309: /*
2.1 frystyk 310: ** Set General Headers
311: */
2.3 frystyk 312: PUBLIC void HTRequest_setGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 313: {
314: if (request) request->GenMask = gnhd;
315: }
316:
2.3 frystyk 317: PUBLIC void HTRequest_addGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 318: {
319: if (request) request->GenMask |= gnhd;
320: }
321:
2.3 frystyk 322: PUBLIC HTGnHd HTRequest_gnHd (HTRequest *request)
2.1 frystyk 323: {
324: return request ? request->GenMask : 0;
325: }
326:
327: /*
328: ** Set Request Headers
329: */
2.3 frystyk 330: PUBLIC void HTRequest_setRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 331: {
332: if (request) request->RequestMask = rqhd;
333: }
334:
2.3 frystyk 335: PUBLIC void HTRequest_addRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 336: {
337: if (request) request->RequestMask |= rqhd;
338: }
339:
2.3 frystyk 340: PUBLIC HTRqHd HTRequest_rqHd (HTRequest *request)
2.1 frystyk 341: {
342: return request ? request->RequestMask : 0;
2.22 frystyk 343: }
344:
345: /*
346: ** Set Response Headers
347: */
348: PUBLIC void HTRequest_setRsHd (HTRequest *request, HTRsHd rshd)
349: {
350: if (request) request->ResponseMask = rshd;
351: }
352:
353: PUBLIC void HTRequest_addRsHd (HTRequest *request, HTRsHd rshd)
354: {
355: if (request) request->ResponseMask |= rshd;
356: }
357:
358: PUBLIC HTRsHd HTRequest_rsHd (HTRequest *request)
359: {
360: return request ? request->ResponseMask : 0;
2.1 frystyk 361: }
362:
363: /*
364: ** Set Entity Headers (for the object)
365: */
2.3 frystyk 366: PUBLIC void HTRequest_setEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 367: {
368: if (request) request->EntityMask = enhd;
369: }
370:
2.3 frystyk 371: PUBLIC void HTRequest_addEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 372: {
373: if (request) request->EntityMask |= enhd;
374: }
375:
2.3 frystyk 376: PUBLIC HTEnHd HTRequest_enHd (HTRequest *request)
2.1 frystyk 377: {
378: return request ? request->EntityMask : 0;
379: }
380:
381: /*
2.18 frystyk 382: ** Access scheme for server
383: */
384: PUBLIC void HTRequest_setAccess (HTRequest * request, char * access)
385: {
386: if (request && access) StrAllocCopy(request->access, access);
387: }
388:
389: PUBLIC CONST char * HTRequest_access (HTRequest * request)
390: {
391: return request ? request->access : NULL;
392: }
393:
394: /*
2.1 frystyk 395: ** Anchor
396: */
2.3 frystyk 397: PUBLIC void HTRequest_setAnchor (HTRequest *request, HTAnchor *anchor)
2.1 frystyk 398: {
399: if (request && anchor) {
400: request->anchor = HTAnchor_parent(anchor);
401: request->childAnchor = ((HTAnchor *) request->anchor != anchor) ?
402: (HTChildAnchor *) anchor : NULL;
403: }
404: }
405:
2.3 frystyk 406: PUBLIC HTParentAnchor * HTRequest_anchor (HTRequest *request)
2.1 frystyk 407: {
408: return request ? request->anchor : NULL;
409: }
410:
411: /*
412: ** Parent anchor for Referer field
413: */
2.3 frystyk 414: PUBLIC void HTRequest_setParent (HTRequest *request, HTParentAnchor *parent)
2.1 frystyk 415: {
416: if (request) request->parentAnchor = parent;
417: }
418:
2.3 frystyk 419: PUBLIC HTParentAnchor * HTRequest_parent (HTRequest *request)
2.1 frystyk 420: {
421: return request ? request->parentAnchor : NULL;
422: }
423:
424: /*
425: ** Output stream
426: */
2.3 frystyk 427: PUBLIC void HTRequest_setOutputStream (HTRequest *request, HTStream *output)
2.1 frystyk 428: {
429: if (request) request->output_stream = output;
430: }
431:
2.4 frystyk 432: PUBLIC HTStream *HTRequest_outputStream (HTRequest *request)
2.1 frystyk 433: {
434: return request ? request->output_stream : NULL;
435: }
436:
437: /*
438: ** Output format
439: */
2.3 frystyk 440: PUBLIC void HTRequest_setOutputFormat (HTRequest *request, HTFormat format)
2.1 frystyk 441: {
442: if (request) request->output_format = format;
443: }
444:
2.4 frystyk 445: PUBLIC HTFormat HTRequest_outputFormat (HTRequest *request)
2.1 frystyk 446: {
447: return request ? request->output_format : NULL;
448: }
449:
450: /*
451: ** Debug stream
452: */
2.3 frystyk 453: PUBLIC void HTRequest_setDebugStream (HTRequest *request, HTStream *debug)
2.1 frystyk 454: {
455: if (request) request->debug_stream = debug;
456: }
457:
2.4 frystyk 458: PUBLIC HTStream *HTRequest_debugStream (HTRequest *request)
2.1 frystyk 459: {
460: return request ? request->debug_stream : NULL;
461: }
462:
463: /*
464: ** Debug Format
465: */
2.3 frystyk 466: PUBLIC void HTRequest_setDebugFormat (HTRequest *request, HTFormat format)
2.1 frystyk 467: {
468: if (request) request->debug_format = format;
469: }
470:
2.4 frystyk 471: PUBLIC HTFormat HTRequest_debugFormat (HTRequest *request)
2.1 frystyk 472: {
473: return request ? request->debug_format : NULL;
474: }
475:
476: /*
477: ** Call back function for context swapping
478: */
2.3 frystyk 479: PUBLIC void HTRequest_setCallback (HTRequest *request, HTRequestCallback *cbf)
2.1 frystyk 480: {
2.3 frystyk 481: if (request) request->callback = cbf;
2.1 frystyk 482: }
483:
2.3 frystyk 484: PUBLIC HTRequestCallback *HTRequest_callback (HTRequest *request)
2.1 frystyk 485: {
486: return request ? request->callback : NULL;
487: }
488:
489: /*
490: ** Context pointer to be used in context call back function
491: */
2.3 frystyk 492: PUBLIC void HTRequest_setContext (HTRequest *request, void *context)
2.1 frystyk 493: {
494: if (request) request->context = context;
495: }
496:
2.3 frystyk 497: PUBLIC void *HTRequest_context (HTRequest *request)
2.1 frystyk 498: {
499: return request ? request->context : NULL;
500: }
501:
502: /*
503: ** Socket mode: preemtive or non-preemtive (blocking or non-blocking)
504: */
2.3 frystyk 505: PUBLIC void HTRequest_setPreemtive (HTRequest *request, BOOL mode)
2.1 frystyk 506: {
507: if (request) request->preemtive = mode;
508: }
509:
2.3 frystyk 510: PUBLIC BOOL HTRequest_preemtive (HTRequest *request)
2.1 frystyk 511: {
512: return request ? request->preemtive : NO;
513: }
514:
515: /*
516: ** Should we use content negotiation?
517: */
2.3 frystyk 518: PUBLIC void HTRequest_setNegotiation (HTRequest *request, BOOL mode)
2.1 frystyk 519: {
520: if (request) request->ContentNegotiation = mode;
521: }
522:
2.3 frystyk 523: PUBLIC BOOL HTRequest_negotiation (HTRequest *request)
2.1 frystyk 524: {
525: return request ? request->ContentNegotiation : NO;
526: }
527:
528: /*
529: ** Bytes read in this request
530: */
2.3 frystyk 531: PUBLIC long HTRequest_bytesRead(HTRequest * request)
2.1 frystyk 532: {
533: return request ? HTNet_bytesRead(request->net) : -1;
534: }
535:
536: /*
2.22.2.1! frystyk 537: ** Bytes written in this request
! 538: */
! 539: PUBLIC long HTRequest_bytesWritten (HTRequest * request)
! 540: {
! 541: return request ? HTNet_bytesWritten(request->net) : -1;
! 542: }
! 543:
! 544: /*
2.1 frystyk 545: ** Kill this request
546: */
2.3 frystyk 547: PUBLIC BOOL HTRequest_kill(HTRequest * request)
2.1 frystyk 548: {
549: return request ? HTNet_kill(request->net) : NO;
550: }
551:
2.11 frystyk 552: /* Error Management
553: ** ----------------
2.1 frystyk 554: ** Returns the error stack if a stream is
555: */
2.11 frystyk 556: PUBLIC HTList * HTRequest_error (HTRequest * request)
2.1 frystyk 557: {
558: return request ? request->error_stack : NULL;
559: }
560:
2.11 frystyk 561: PUBLIC void HTRequest_setError (HTRequest * request, HTList * list)
562: {
563: if (request) request->error_stack = list;
564: }
565:
566: PUBLIC BOOL HTRequest_addError (HTRequest * request,
567: HTSeverity severity,
568: BOOL ignore,
569: int element,
570: void * par,
571: unsigned int length,
572: char * where)
573: {
574: if (request) {
575: if (!request->error_stack) request->error_stack = HTList_new();
576: return HTError_add(request->error_stack, severity, ignore, element,
577: par, length, where);
578: }
579: return NO;
580: }
581:
582: PUBLIC BOOL HTRequest_addSystemError (HTRequest * request,
583: HTSeverity severity,
584: int errornumber,
585: BOOL ignore,
586: char * syscall)
587: {
588: if (request) {
589: if (!request->error_stack) request->error_stack = HTList_new();
590: return HTError_addSystem(request->error_stack, severity, errornumber,
591: ignore, syscall);
592: }
593: return NO;
594: }
595:
2.1 frystyk 596: /*
597: ** When to retry a request if HT_RETRY
598: ** Returns -1 if not available
599: */
600: PUBLIC time_t HTRequest_retryTime (HTRequest * request)
601: {
602: return request ? request->retry_after : -1;
603: }
604:
605: /*
2.22.2.1! frystyk 606: ** Redirection informantion
! 607: */
! 608: PUBLIC HTAnchor * HTRequest_redirection (HTRequest * request)
! 609: {
! 610: return (request ? request->redirectionAnchor : NULL);
! 611: }
! 612:
! 613: /*
2.1 frystyk 614: ** Set max number of automatic reload. Default is HT_MAX_RELOADS
615: */
2.3 frystyk 616: PUBLIC BOOL HTRequest_setMaxRetry (int newmax)
2.1 frystyk 617: {
618: if (newmax > 0) {
619: HTMaxRetry = newmax;
620: return YES;
621: }
622: return NO;
623: }
624:
2.3 frystyk 625: PUBLIC int HTRequest_maxRetry (void)
2.1 frystyk 626: {
627: return HTMaxRetry;
628: }
629:
630: /*
631: ** Should we try again?
632: ** --------------------
633: ** Returns YES if we are to retry the load, NO otherwise. We check
634: ** this so that we don't go into an infinte loop
635: */
2.3 frystyk 636: PUBLIC BOOL HTRequest_retry (HTRequest *request)
2.1 frystyk 637: {
638: return (request && request->retrys < HTMaxRetry-1);
639: }
640:
2.9 frystyk 641: /*
642: ** Priority to be inherited by all HTNet object hanging off this request
643: ** The priority can later be chaned by calling the HTNet object directly
644: */
645: PUBLIC BOOL HTRequest_setPriority (HTRequest * request, HTPriority priority)
646: {
647: if (request) {
648: request->priority = priority;
649: return YES;
650: }
651: return NO;
652: }
653:
654: PUBLIC HTPriority HTRequest_priority (HTRequest * request)
655: {
2.19 frystyk 656: return (request ? request->priority : HT_PRIORITY_INV);
2.9 frystyk 657: }
658:
2.18 frystyk 659: /*
660: ** Get and set the NET manager
661: */
662: PUBLIC BOOL HTRequest_setNet (HTRequest * request, HTNet * net)
663: {
664: if (request) {
665: request->net = net;
666: return YES;
667: }
668: return NO;
669: }
670:
671: PUBLIC HTNet * HTRequest_net (HTRequest * request)
672: {
673: return (request ? request->net : NULL);
674: }
675:
2.1 frystyk 676: /* ------------------------------------------------------------------------- */
677: /* POST WEB METHODS */
678: /* ------------------------------------------------------------------------- */
679:
680: /*
681: ** Add a destination request to this source request structure so that we
682: ** build the internal request representation of the POST web
683: ** Returns YES if OK, else NO
684: */
2.22.2.1! frystyk 685: PUBLIC BOOL HTRequest_addDestination (HTRequest * src, HTRequest * dest)
2.1 frystyk 686: {
687: if (src && dest) {
2.22.2.1! frystyk 688: dest->source = src->source = src;
2.1 frystyk 689: if (!src->mainDestination) {
690: src->mainDestination = dest;
691: src->destRequests = 1;
2.22.2.1! frystyk 692: if (WWWTRACE)
! 693: TTYPrint(TDEST,"POSTWeb..... Adding dest %p to src %p\n",
! 694: dest, src);
2.1 frystyk 695: return YES;
696: } else {
2.22.2.1! frystyk 697: if (!src->destinations) src->destinations = HTList_new();
2.1 frystyk 698: if (HTList_addObject(src->destinations, (void *) dest)==YES) {
699: src->destRequests++;
2.22.2.1! frystyk 700: if (WWWTRACE)
! 701: TTYPrint(TDEST,"POSTWeb..... Adding dest %p to src %p\n",
! 702: dest, src);
2.1 frystyk 703: return YES;
704: }
705: }
706: }
707: return NO;
708: }
709:
710: /*
711: ** Remove a destination request from this source request structure
2.22.2.1! frystyk 712: ** Remember only to delete the internal request objects as the other
! 713: ** comes from the application!
2.1 frystyk 714: ** Returns YES if OK, else NO
715: */
2.22.2.1! frystyk 716: PUBLIC BOOL HTRequest_removeDestination (HTRequest * dest)
2.1 frystyk 717: {
718: BOOL found=NO;
719: if (dest && dest->source) {
720: HTRequest *src = dest->source;
721: if (src->mainDestination == dest) {
722: dest->source = NULL;
723: src->mainDestination = NULL;
724: src->destRequests--;
725: found = YES;
2.22.2.1! frystyk 726: } else if (src->destinations) {
2.1 frystyk 727: if (HTList_removeObject(src->destinations, (void *) dest)) {
728: src->destRequests--;
729: found = YES;
730: }
731: }
732: if (found) {
2.22.2.1! frystyk 733: if (dest->internal) HTRequest_delete(dest);
2.5 frystyk 734: if (WWWTRACE)
2.22.2.1! frystyk 735: TTYPrint(TDEST, "POSTWeb..... Deleting dest %p from src %p\n",
! 736: dest, src);
2.1 frystyk 737: }
2.22.2.1! frystyk 738: if (src->destRequests <= 0) {
2.5 frystyk 739: if (WWWTRACE)
2.22.2.1! frystyk 740: TTYPrint(TDEST, "POSTWeb..... terminated\n");
! 741: if (src->internal) HTRequest_delete(src);
2.1 frystyk 742: }
743: }
744: return found;
745: }
746:
747: /*
2.22.2.1! frystyk 748: ** Check to see whether all destinations are ready. If so then enable the
! 749: ** source as ready for reading.
! 750: ** Returns YES if all dests are ready, NO otherwise
! 751: */
! 752: PUBLIC BOOL HTRequest_destinationsReady (HTRequest * me)
! 753: {
! 754: HTRequest * source = me ? me->source : NULL;
! 755: if (source) {
! 756: if (source->destStreams == source->destRequests) {
! 757: HTNet * net = source->net;
! 758: if (WWWTRACE)
! 759: TTYPrint(TDEST, "POSTWeb..... All destinations are ready!\n");
! 760: if (net) /* Might already have finished */
! 761: HTEvent_Register(net->sockfd, source, (SockOps) FD_READ,
! 762: net->cbf, net->priority);
! 763: return YES;
! 764: }
! 765: }
! 766: return NO;
! 767: }
! 768:
! 769: /*
! 770: ** Find the source request object and make the link between the
2.1 frystyk 771: ** source output stream and the destination input stream. There can be
772: ** a conversion between the two streams!
773: ** Returns YES if link is made, NO otherwise
774: */
2.3 frystyk 775: PUBLIC BOOL HTRequest_linkDestination (HTRequest *dest)
2.1 frystyk 776: {
777: if (dest && dest->input_stream && dest->source && dest!=dest->source) {
778: HTRequest *source = dest->source;
779: HTStream *pipe = HTStreamStack(source->output_format,
780: dest->input_format,
781: dest->input_stream,
782: dest, YES);
783:
784: /* Check if we are the only one - else spawn off T streams */
785: /* @@@ We don't do this yet @@@ */
786:
2.22.2.1! frystyk 787: /* Now set up output stream of the source */
! 788: if (source->output_stream)
! 789: (*source->output_stream->isa->_free)(source->output_stream);
2.1 frystyk 790: source->output_stream = pipe ? pipe : dest->input_stream;
791:
2.22.2.1! frystyk 792: if (WWWTRACE)
! 793: TTYPrint(TDEST,"POSTWeb..... Linking dest %p to src %p\n",
! 794: dest, source);
2.1 frystyk 795: if (++source->destStreams == source->destRequests) {
796: HTNet *net = source->net;
2.22.2.1! frystyk 797: if (WWWTRACE)
! 798: TTYPrint(TDEST, "POSTWeb..... All destinations ready!\n");
2.1 frystyk 799: if (net) /* Might already have finished */
800: HTEvent_Register(net->sockfd, source, (SockOps) FD_READ,
801: net->cbf, net->priority);
802: return YES;
803: }
804: }
805: return NO;
806: }
807:
808: /*
809: ** Remove a feed stream to a destination request from this source
810: ** request structure. When all feeds are removed the request tree is
811: ** ready to take down and the operation can be terminated.
812: ** Returns YES if removed, else NO
813: */
2.3 frystyk 814: PUBLIC BOOL HTRequest_unlinkDestination (HTRequest *dest)
2.1 frystyk 815: {
816: BOOL found = NO;
817: if (dest && dest->source && dest != dest->source) {
818: HTRequest *src = dest->source;
819: if (src->mainDestination == dest) {
820: src->output_stream = NULL;
821: if (dest->input_stream)
822: (*dest->input_stream->isa->_free)(dest->input_stream);
823: found = YES;
824: } else if (src->destinations) {
825:
826: /* LOOK THROUGH THE LIST AND FIND THE RIGHT ONE */
827:
828: }
829: if (found) {
830: src->destStreams--;
2.22.2.1! frystyk 831: if (WWWTRACE)
! 832: TTYPrint(TDEST, "POSTWeb..... Unlinking dest %p from src %p\n",
! 833: dest, src);
2.1 frystyk 834: return YES;
835: }
836: }
837: return NO;
838: }
839:
840: /*
841: ** Removes all request structures in this PostWeb.
842: */
2.3 frystyk 843: PUBLIC BOOL HTRequest_removePostWeb (HTRequest *me)
2.1 frystyk 844: {
845: if (me && me->source) {
846: HTRequest *source = me->source;
847:
848: /* Kill main destination */
849: if (source->mainDestination)
850: HTRequest_removeDestination(source->mainDestination);
851:
852: /* Kill all other destinations */
853: if (source->destinations) {
854: HTList *cur = source->destinations;
855: HTRequest *pres;
856: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
857: HTRequest_removeDestination(pres);
858: }
859:
860: /* Remove source request */
861: HTRequest_removeDestination(source);
862: return YES;
863: }
864: return NO;
865: }
866:
867: /*
868: ** Kills all threads in a POST WEB connected to this request but
2.22.2.1! frystyk 869: ** NOT this request itself. We also keep the request structures.
2.1 frystyk 870: ** Some requests might be preemtive, for example a SMTP request (when
871: ** that has been implemented). However, this will be handled internally
872: ** in the load function.
873: */
2.3 frystyk 874: PUBLIC BOOL HTRequest_killPostWeb (HTRequest *me)
2.1 frystyk 875: {
876: if (me && me->source) {
877: HTRequest *source = me->source;
2.22.2.1! frystyk 878: if (WWWTRACE) TTYPrint(TDEST, "POSTWeb..... Killing\n");
2.1 frystyk 879:
2.22.2.1! frystyk 880: /*
! 881: ** Kill source. The stream tree is now freed so we have to build
! 882: ** that again. This is done in HTRequest_linkDestination()
! 883: */
! 884: if (me != source) {
! 885: HTNet_kill(source->net);
! 886: source->output_stream = NULL;
! 887: }
2.1 frystyk 888:
889: /* Kill all other destinations */
890: if (source->destinations) {
891: HTList *cur = source->destinations;
892: HTRequest *pres;
893: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
2.22.2.1! frystyk 894: if (me != pres) HTNet_kill(pres->net);
2.1 frystyk 895: }
2.22.2.1! frystyk 896:
! 897: /* Kill main destination */
! 898: if (source->mainDestination && me != source->mainDestination)
! 899: HTNet_kill(source->mainDestination->net);
2.1 frystyk 900: return YES;
901: }
902: return NO;
903: }
904:
905: /* --------------------------------------------------------------------------*/
906: /* Physical Anchor Address Manager */
907: /* --------------------------------------------------------------------------*/
2.16 frystyk 908: #if 0
2.1 frystyk 909: /* Find physical name and access protocol
910: ** --------------------------------------
911: **
912: ** Checks for Cache, proxy, and gateway (in that order)
913: **
914: ** On exit,
915: ** returns HT_NO_ACCESS no protocol module found
916: ** HT_FORBIDDEN Error has occured.
917: ** HT_OK Success
918: **
919: */
920: PRIVATE int get_physical (HTRequest *req)
921: {
922: char * addr = HTAnchor_address((HTAnchor*)req->anchor); /* free me */
2.14 frystyk 923: HTList *list = HTRule_global();
924: char * physical = HTRule_translate(list, addr, NO);
925: if (!physical) {
926: free(addr);
927: return HT_FORBIDDEN;
2.1 frystyk 928: }
2.14 frystyk 929: HTAnchor_setPhysical(req->anchor, physical);
930: free(physical);
2.1 frystyk 931:
932: /*
933: ** Check local Disk Cache (if we are not forced to reload), then
934: ** for proxy, and finally gateways
935: */
936: {
937: char *newaddr=NULL;
938: if (req->reload != HT_FORCE_RELOAD &&
939: (newaddr = HTCache_getReference(addr))) {
940: if (req->reload != HT_CACHE_REFRESH) {
941: HTAnchor_setPhysical(req->anchor, newaddr);
942: HTAnchor_setCacheHit(req->anchor, YES);
943: } else { /* If refresh version in file cache */
944: req->RequestMask |= (HT_IMS + HT_NO_CACHE);
945: }
2.8 frystyk 946: } else if ((newaddr = HTProxy_find(addr))) {
2.1 frystyk 947: StrAllocCat(newaddr, addr);
948: req->using_proxy = YES;
949: HTAnchor_setPhysical(req->anchor, newaddr);
2.8 frystyk 950: } else if ((newaddr = HTGateway_find(addr))) {
2.1 frystyk 951: char * path = HTParse(addr, "",
952: PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
953: /* Chop leading / off to make host into part of path */
954: char * gatewayed = HTParse(path+1, newaddr, PARSE_ALL);
955: HTAnchor_setPhysical(req->anchor, gatewayed);
956: free(path);
957: free(gatewayed);
958: } else {
959: req->using_proxy = NO; /* We don't use proxy or gateway */
960: }
961: FREE(newaddr);
962: }
963: FREE(addr);
964:
965: /* Set the access scheme on our way out */
2.12 frystyk 966: return (HTProtocol_find(req, req->anchor)==YES) ? HT_OK : HT_NO_ACCESS;
2.1 frystyk 967: }
2.16 frystyk 968: #endif
2.1 frystyk 969:
970: /* --------------------------------------------------------------------------*/
971: /* Document Loader */
972: /* --------------------------------------------------------------------------*/
973:
974: /* Request a resource
975: ** ------------------
976: ** This is an internal routine, which has an address AND a matching
977: ** anchor. (The public routines are called with one OR the other.)
978: ** Returns:
979: ** YES if request has been registered (success)
980: ** NO an error occured
981: */
2.9 frystyk 982: PUBLIC BOOL HTLoad (HTRequest * request, BOOL recursive)
2.1 frystyk 983: {
984: if (!request || !request->anchor) {
2.10 frystyk 985: if (PROT_TRACE) TTYPrint(TDEST, "Load Start.. Bad argument\n");
2.1 frystyk 986: return NO;
987: }
2.14 frystyk 988: if (request->method == METHOD_INVALID) request->method = METHOD_GET;
2.16 frystyk 989: if (!recursive && request->error_stack) {
990: HTError_deleteAll(request->error_stack);
991: request->error_stack = NULL;
992: }
2.18 frystyk 993: return HTNet_newClient(request);
2.1 frystyk 994: }
995:
2.18 frystyk 996: /* Serv a resource
997: ** ---------------
998: ** This function initiates the server side of a request and starts
999: ** serving it back accross the network.
1000: ** Returns:
1001: ** YES if request has been registered (success)
1002: ** NO an error occured
1003: */
2.20 frystyk 1004: PUBLIC BOOL HTServ (HTRequest * request, SOCKET master, BOOL recursive)
2.18 frystyk 1005: {
1006: if (!request || !request->access) {
1007: if (PROT_TRACE) TTYPrint(TDEST, "Serv Start.. Bad argument\n");
1008: return NO;
1009: }
1010: if (!recursive && request->error_stack) {
1011: HTError_deleteAll(request->error_stack);
1012: request->error_stack = NULL;
1013: }
2.20 frystyk 1014: return HTNet_newServer(request, master);
2.14 frystyk 1015: }
Webmaster