Annotation of libwww/Library/src/HTReqMan.c, revision 2.21
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;
80: me->EntityMask = DEFAULT_ENTITY_HEADERS;
81:
82: /* Default retry after value */
83: me->retry_after = -1;
2.19 frystyk 84: me->priority = HT_PRIORITY_MAX;
2.1 frystyk 85:
86: /* Content negotiation */
87: me->ContentNegotiation = NO; /* Do this by default */
88:
2.13 frystyk 89: #ifdef WWW_WIN_ASYNC
90: HTEvent_winHandle(me);
2.1 frystyk 91: #endif
92: return me;
93: }
94:
2.18 frystyk 95: /* HTRequest_dup
96: ** -------------
97: ** Creates a new HTRequest object as a duplicate of the src request.
98: ** Returns YES if OK, else NO
99: */
100: PUBLIC HTRequest * HTRequest_dup (HTRequest * src)
101: {
102: HTRequest * me;
103: if (!src) return NO;
104: if ((me = (HTRequest *) calloc(1, sizeof(HTRequest))) == NULL)
105: outofmem(__FILE__, "HTRequest_dup");
106: memcpy(me, src, sizeof(HTRequest));
107: return me;
108: }
2.1 frystyk 109:
110: /* Delete a request structure
111: ** --------------------------
112: */
2.3 frystyk 113: PUBLIC void HTRequest_delete (HTRequest * request)
2.1 frystyk 114: {
115: if (request) {
116: FREE(request->redirect);
2.11 frystyk 117: FREE(request->boundary);
2.1 frystyk 118: FREE(request->authenticate);
2.11 frystyk 119: if (request->error_stack) HTError_deleteAll(request->error_stack);
2.13 frystyk 120:
2.18 frystyk 121: FREE(request->access);
122:
2.13 frystyk 123: FREE(request->authorization);
124: FREE(request->prot_template);
125: FREE(request->dialog_msg);
2.1 frystyk 126:
127: if (request->net) /* Break connection to HTNet */
128: request->net->request = NULL;
129:
130: /* These are temporary until we get a MIME thingy */
131: FREE(request->redirect);
132: FREE(request->WWWAAScheme);
133: FREE(request->WWWAARealm);
134: FREE(request->WWWprotection);
135:
136: FREE(request);
137: }
138: }
139:
140: /*
141: ** Method
142: */
2.3 frystyk 143: PUBLIC void HTRequest_setMethod (HTRequest *request, HTMethod method)
2.1 frystyk 144: {
145: if (request) request->method = method;
146: }
147:
2.3 frystyk 148: PUBLIC HTMethod HTRequest_method (HTRequest *request)
2.1 frystyk 149: {
150: return request ? request->method : METHOD_INVALID;
151: }
152:
153: /*
154: ** Reload Mode
155: */
2.3 frystyk 156: PUBLIC void HTRequest_setReloadMode (HTRequest *request, HTReload mode)
2.1 frystyk 157: {
158: if (request) request->reload = mode;
159: }
160:
2.3 frystyk 161: PUBLIC HTReload HTRequest_reloadMode (HTRequest *request)
2.1 frystyk 162: {
163: return request ? request->reload : HT_ANY_VERSION;
164: }
165:
166: /*
167: ** Accept Format Types
168: ** list can be NULL
169: */
2.6 frystyk 170: PUBLIC void HTRequest_setConversion (HTRequest *request, HTList *type,
171: BOOL override)
2.1 frystyk 172: {
173: if (request) {
174: request->conversions = type;
175: request->conv_local = override;
176: }
177: }
178:
2.6 frystyk 179: PUBLIC HTList * HTRequest_conversion (HTRequest *request)
2.1 frystyk 180: {
181: return request ? request->conversions : NULL;
182: }
183:
184: /*
185: ** Accept Encoding
186: ** list can be NULL
187: */
2.3 frystyk 188: PUBLIC void HTRequest_setEncoding (HTRequest *request, HTList *enc,
189: BOOL override)
2.1 frystyk 190: {
191: if (request) {
192: request->encodings = enc;
193: request->enc_local = override;
194: }
195: }
196:
2.3 frystyk 197: PUBLIC HTList * HTRequest_encoding (HTRequest *request)
2.1 frystyk 198: {
199: return request ? request->encodings : NULL;
200: }
201:
202: /*
203: ** Accept Language
204: ** list can be NULL
205: */
2.3 frystyk 206: PUBLIC void HTRequest_setLanguage (HTRequest *request, HTList *lang,
207: BOOL override)
2.1 frystyk 208: {
209: if (request) {
210: request->languages = lang;
211: request->lang_local = override;
212: }
213: }
214:
2.3 frystyk 215: PUBLIC HTList * HTRequest_language (HTRequest *request)
2.1 frystyk 216: {
217: return request ? request->languages : NULL;
218: }
219:
220: /*
221: ** Accept Charset
222: ** list can be NULL
223: */
2.3 frystyk 224: PUBLIC void HTRequest_setCharset (HTRequest *request, HTList *charset,
225: BOOL override)
2.1 frystyk 226: {
227: if (request) {
228: request->charsets = charset;
229: request->char_local = override;
230: }
231: }
232:
2.3 frystyk 233: PUBLIC HTList * HTRequest_charset (HTRequest *request)
2.1 frystyk 234: {
235: return request ? request->charsets : NULL;
236: }
237:
238: /*
2.9 frystyk 239: ** Extra Header Generators. list can be NULL
240: */
241: PUBLIC void HTRequest_setGenerator (HTRequest *request, HTList *generator,
242: BOOL override)
243: {
244: if (request) {
245: request->generators = generator;
246: request->gens_local = override;
247: }
248: }
249:
250: PUBLIC HTList * HTRequest_generator (HTRequest *request, BOOL *override)
251: {
252: if (request) {
253: *override = request->gens_local;
254: return request->generators;
255: }
256: return NULL;
257: }
258:
259: /*
260: ** Extra Header Parsers. list can be NULL
261: */
262: PUBLIC void HTRequest_setParser (HTRequest *request, HTList *parser,
263: BOOL override)
264: {
265: if (request) {
266: request->parsers = parser;
267: request->pars_local = override;
268: }
269: }
270:
271: PUBLIC HTList * HTRequest_parser (HTRequest *request, BOOL *override)
272: {
273: if (request) {
274: *override = request->pars_local;
275: return request->parsers;
276: }
277: return NULL;
278: }
279:
280: /*
2.1 frystyk 281: ** Set General Headers
282: */
2.3 frystyk 283: PUBLIC void HTRequest_setGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 284: {
285: if (request) request->GenMask = gnhd;
286: }
287:
2.3 frystyk 288: PUBLIC void HTRequest_addGnHd (HTRequest *request, HTGnHd gnhd)
2.1 frystyk 289: {
290: if (request) request->GenMask |= gnhd;
291: }
292:
2.3 frystyk 293: PUBLIC HTGnHd HTRequest_gnHd (HTRequest *request)
2.1 frystyk 294: {
295: return request ? request->GenMask : 0;
296: }
297:
298: /*
299: ** Set Request Headers
300: */
2.3 frystyk 301: PUBLIC void HTRequest_setRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 302: {
303: if (request) request->RequestMask = rqhd;
304: }
305:
2.3 frystyk 306: PUBLIC void HTRequest_addRqHd (HTRequest *request, HTRqHd rqhd)
2.1 frystyk 307: {
308: if (request) request->RequestMask |= rqhd;
309: }
310:
2.3 frystyk 311: PUBLIC HTRqHd HTRequest_rqHd (HTRequest *request)
2.1 frystyk 312: {
313: return request ? request->RequestMask : 0;
314: }
315:
316: /*
317: ** Set Entity Headers (for the object)
318: */
2.3 frystyk 319: PUBLIC void HTRequest_setEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 320: {
321: if (request) request->EntityMask = enhd;
322: }
323:
2.3 frystyk 324: PUBLIC void HTRequest_addEnHd (HTRequest *request, HTEnHd enhd)
2.1 frystyk 325: {
326: if (request) request->EntityMask |= enhd;
327: }
328:
2.3 frystyk 329: PUBLIC HTEnHd HTRequest_enHd (HTRequest *request)
2.1 frystyk 330: {
331: return request ? request->EntityMask : 0;
332: }
333:
334: /*
2.18 frystyk 335: ** Access scheme for server
336: */
337: PUBLIC void HTRequest_setAccess (HTRequest * request, char * access)
338: {
339: if (request && access) StrAllocCopy(request->access, access);
340: }
341:
342: PUBLIC CONST char * HTRequest_access (HTRequest * request)
343: {
344: return request ? request->access : NULL;
345: }
346:
347: /*
2.1 frystyk 348: ** Anchor
349: */
2.3 frystyk 350: PUBLIC void HTRequest_setAnchor (HTRequest *request, HTAnchor *anchor)
2.1 frystyk 351: {
352: if (request && anchor) {
353: request->anchor = HTAnchor_parent(anchor);
354: request->childAnchor = ((HTAnchor *) request->anchor != anchor) ?
355: (HTChildAnchor *) anchor : NULL;
356: }
357: }
358:
2.3 frystyk 359: PUBLIC HTParentAnchor * HTRequest_anchor (HTRequest *request)
2.1 frystyk 360: {
361: return request ? request->anchor : NULL;
362: }
363:
364: /*
365: ** Parent anchor for Referer field
366: */
2.3 frystyk 367: PUBLIC void HTRequest_setParent (HTRequest *request, HTParentAnchor *parent)
2.1 frystyk 368: {
369: if (request) request->parentAnchor = parent;
370: }
371:
2.3 frystyk 372: PUBLIC HTParentAnchor * HTRequest_parent (HTRequest *request)
2.1 frystyk 373: {
374: return request ? request->parentAnchor : NULL;
375: }
376:
377: /*
378: ** Output stream
379: */
2.3 frystyk 380: PUBLIC void HTRequest_setOutputStream (HTRequest *request, HTStream *output)
2.1 frystyk 381: {
382: if (request) request->output_stream = output;
383: }
384:
2.4 frystyk 385: PUBLIC HTStream *HTRequest_outputStream (HTRequest *request)
2.1 frystyk 386: {
387: return request ? request->output_stream : NULL;
388: }
389:
390: /*
391: ** Output format
392: */
2.3 frystyk 393: PUBLIC void HTRequest_setOutputFormat (HTRequest *request, HTFormat format)
2.1 frystyk 394: {
395: if (request) request->output_format = format;
396: }
397:
2.4 frystyk 398: PUBLIC HTFormat HTRequest_outputFormat (HTRequest *request)
2.1 frystyk 399: {
400: return request ? request->output_format : NULL;
401: }
402:
403: /*
404: ** Debug stream
405: */
2.3 frystyk 406: PUBLIC void HTRequest_setDebugStream (HTRequest *request, HTStream *debug)
2.1 frystyk 407: {
408: if (request) request->debug_stream = debug;
409: }
410:
2.4 frystyk 411: PUBLIC HTStream *HTRequest_debugStream (HTRequest *request)
2.1 frystyk 412: {
413: return request ? request->debug_stream : NULL;
414: }
415:
416: /*
417: ** Debug Format
418: */
2.3 frystyk 419: PUBLIC void HTRequest_setDebugFormat (HTRequest *request, HTFormat format)
2.1 frystyk 420: {
421: if (request) request->debug_format = format;
422: }
423:
2.4 frystyk 424: PUBLIC HTFormat HTRequest_debugFormat (HTRequest *request)
2.1 frystyk 425: {
426: return request ? request->debug_format : NULL;
427: }
428:
429: /*
430: ** Call back function for context swapping
431: */
2.3 frystyk 432: PUBLIC void HTRequest_setCallback (HTRequest *request, HTRequestCallback *cbf)
2.1 frystyk 433: {
2.3 frystyk 434: if (request) request->callback = cbf;
2.1 frystyk 435: }
436:
2.3 frystyk 437: PUBLIC HTRequestCallback *HTRequest_callback (HTRequest *request)
2.1 frystyk 438: {
439: return request ? request->callback : NULL;
440: }
441:
442: /*
443: ** Context pointer to be used in context call back function
444: */
2.3 frystyk 445: PUBLIC void HTRequest_setContext (HTRequest *request, void *context)
2.1 frystyk 446: {
447: if (request) request->context = context;
448: }
449:
2.3 frystyk 450: PUBLIC void *HTRequest_context (HTRequest *request)
2.1 frystyk 451: {
452: return request ? request->context : NULL;
453: }
454:
455: /*
456: ** Socket mode: preemtive or non-preemtive (blocking or non-blocking)
457: */
2.3 frystyk 458: PUBLIC void HTRequest_setPreemtive (HTRequest *request, BOOL mode)
2.1 frystyk 459: {
460: if (request) request->preemtive = mode;
461: }
462:
2.3 frystyk 463: PUBLIC BOOL HTRequest_preemtive (HTRequest *request)
2.1 frystyk 464: {
465: return request ? request->preemtive : NO;
466: }
467:
468: /*
469: ** Should we use content negotiation?
470: */
2.3 frystyk 471: PUBLIC void HTRequest_setNegotiation (HTRequest *request, BOOL mode)
2.1 frystyk 472: {
473: if (request) request->ContentNegotiation = mode;
474: }
475:
2.3 frystyk 476: PUBLIC BOOL HTRequest_negotiation (HTRequest *request)
2.1 frystyk 477: {
478: return request ? request->ContentNegotiation : NO;
479: }
480:
481: /*
482: ** Bytes read in this request
483: */
2.3 frystyk 484: PUBLIC long HTRequest_bytesRead(HTRequest * request)
2.1 frystyk 485: {
486: return request ? HTNet_bytesRead(request->net) : -1;
487: }
488:
489: /*
490: ** Kill this request
491: */
2.3 frystyk 492: PUBLIC BOOL HTRequest_kill(HTRequest * request)
2.1 frystyk 493: {
494: return request ? HTNet_kill(request->net) : NO;
495: }
496:
2.11 frystyk 497: /* Error Management
498: ** ----------------
2.1 frystyk 499: ** Returns the error stack if a stream is
500: */
2.11 frystyk 501: PUBLIC HTList * HTRequest_error (HTRequest * request)
2.1 frystyk 502: {
503: return request ? request->error_stack : NULL;
504: }
505:
2.11 frystyk 506: PUBLIC void HTRequest_setError (HTRequest * request, HTList * list)
507: {
508: if (request) request->error_stack = list;
509: }
510:
511: PUBLIC BOOL HTRequest_addError (HTRequest * request,
512: HTSeverity severity,
513: BOOL ignore,
514: int element,
515: void * par,
516: unsigned int length,
517: char * where)
518: {
519: if (request) {
520: if (!request->error_stack) request->error_stack = HTList_new();
521: return HTError_add(request->error_stack, severity, ignore, element,
522: par, length, where);
523: }
524: return NO;
525: }
526:
527: PUBLIC BOOL HTRequest_addSystemError (HTRequest * request,
528: HTSeverity severity,
529: int errornumber,
530: BOOL ignore,
531: char * syscall)
532: {
533: if (request) {
534: if (!request->error_stack) request->error_stack = HTList_new();
535: return HTError_addSystem(request->error_stack, severity, errornumber,
536: ignore, syscall);
537: }
538: return NO;
539: }
540:
2.1 frystyk 541: /*
542: ** When to retry a request if HT_RETRY
543: ** Returns -1 if not available
544: */
545: PUBLIC time_t HTRequest_retryTime (HTRequest * request)
546: {
547: return request ? request->retry_after : -1;
548: }
549:
550: /*
551: ** Set max number of automatic reload. Default is HT_MAX_RELOADS
552: */
2.3 frystyk 553: PUBLIC BOOL HTRequest_setMaxRetry (int newmax)
2.1 frystyk 554: {
555: if (newmax > 0) {
556: HTMaxRetry = newmax;
557: return YES;
558: }
559: return NO;
560: }
561:
2.3 frystyk 562: PUBLIC int HTRequest_maxRetry (void)
2.1 frystyk 563: {
564: return HTMaxRetry;
565: }
566:
567: /*
568: ** Should we try again?
569: ** --------------------
570: ** Returns YES if we are to retry the load, NO otherwise. We check
571: ** this so that we don't go into an infinte loop
572: */
2.3 frystyk 573: PUBLIC BOOL HTRequest_retry (HTRequest *request)
2.1 frystyk 574: {
575: return (request && request->retrys < HTMaxRetry-1);
576: }
577:
2.9 frystyk 578: /*
579: ** Priority to be inherited by all HTNet object hanging off this request
580: ** The priority can later be chaned by calling the HTNet object directly
581: */
582: PUBLIC BOOL HTRequest_setPriority (HTRequest * request, HTPriority priority)
583: {
584: if (request) {
585: request->priority = priority;
586: return YES;
587: }
588: return NO;
589: }
590:
591: PUBLIC HTPriority HTRequest_priority (HTRequest * request)
592: {
2.19 frystyk 593: return (request ? request->priority : HT_PRIORITY_INV);
2.9 frystyk 594: }
595:
2.18 frystyk 596: /*
597: ** Get and set the NET manager
598: */
599: PUBLIC BOOL HTRequest_setNet (HTRequest * request, HTNet * net)
600: {
601: if (request) {
602: request->net = net;
603: return YES;
604: }
605: return NO;
606: }
607:
608: PUBLIC HTNet * HTRequest_net (HTRequest * request)
609: {
610: return (request ? request->net : NULL);
611: }
612:
2.1 frystyk 613: /* ------------------------------------------------------------------------- */
614: /* POST WEB METHODS */
615: /* ------------------------------------------------------------------------- */
616:
617: /*
618: ** Add a destination request to this source request structure so that we
619: ** build the internal request representation of the POST web
620: ** Returns YES if OK, else NO
621: */
2.3 frystyk 622: PUBLIC BOOL HTRequest_addDestination (HTRequest *src, HTRequest *dest)
2.1 frystyk 623: {
624: if (src && dest) {
625: if (!src->mainDestination) {
626: src->mainDestination = dest;
627: src->destRequests = 1;
628: return YES;
629: } else {
630: if (!src->destinations)
631: src->destinations = HTList_new();
632: if (HTList_addObject(src->destinations, (void *) dest)==YES) {
633: src->destRequests++;
634: return YES;
635: }
636: }
637: }
638: return NO;
639: }
640:
641: /*
642: ** Remove a destination request from this source request structure
643: ** Remember not to delete the main destination as it comes from the
644: ** application!
645: ** Returns YES if OK, else NO
646: */
2.3 frystyk 647: PUBLIC BOOL HTRequest_removeDestination (HTRequest *dest)
2.1 frystyk 648: {
649: BOOL found=NO;
650: if (dest && dest->source) {
651: HTRequest *src = dest->source;
652: if (src->mainDestination == dest) {
653: dest->source = NULL;
654: src->mainDestination = NULL;
655: src->destRequests--;
656: found = YES;
657: } if (src->destinations) {
658: if (HTList_removeObject(src->destinations, (void *) dest)) {
659: HTRequest_delete(dest);
660: src->destRequests--;
661: found = YES;
662: }
663: }
664: if (found) {
2.5 frystyk 665: if (WWWTRACE)
2.10 frystyk 666: TTYPrint(TDEST, "Destination. %p removed from %p\n",
2.1 frystyk 667: dest, src);
668: }
669: if (!src->destRequests) {
2.5 frystyk 670: if (WWWTRACE)
2.10 frystyk 671: TTYPrint(TDEST, "Destination. PostWeb terminated\n");
2.1 frystyk 672: HTRequest_delete(src);
673: }
674: }
675: return found;
676: }
677:
678: /*
679: ** Find the source request structure and make the link between the
680: ** source output stream and the destination input stream. There can be
681: ** a conversion between the two streams!
682: ** Returns YES if link is made, NO otherwise
683: */
2.3 frystyk 684: PUBLIC BOOL HTRequest_linkDestination (HTRequest *dest)
2.1 frystyk 685: {
686: if (dest && dest->input_stream && dest->source && dest!=dest->source) {
687: HTRequest *source = dest->source;
688: HTStream *pipe = HTStreamStack(source->output_format,
689: dest->input_format,
690: dest->input_stream,
691: dest, YES);
692:
693: /* Check if we are the only one - else spawn off T streams */
694:
695: /* @@@ We don't do this yet @@@ */
696:
697: source->output_stream = pipe ? pipe : dest->input_stream;
698:
699: if (STREAM_TRACE)
2.10 frystyk 700: TTYPrint(TDEST,"Destination. Linked %p to source %p\n",dest,source);
2.1 frystyk 701: if (++source->destStreams == source->destRequests) {
702: HTNet *net = source->net;
703: if (STREAM_TRACE)
2.10 frystyk 704: TTYPrint(TDEST, "Destination. All destinations ready!\n");
2.1 frystyk 705: if (net) /* Might already have finished */
706: HTEvent_Register(net->sockfd, source, (SockOps) FD_READ,
707: net->cbf, net->priority);
708: return YES;
709: }
710: }
711: return NO;
712: }
713:
714: /*
715: ** Remove a feed stream to a destination request from this source
716: ** request structure. When all feeds are removed the request tree is
717: ** ready to take down and the operation can be terminated.
718: ** Returns YES if removed, else NO
719: */
2.3 frystyk 720: PUBLIC BOOL HTRequest_unlinkDestination (HTRequest *dest)
2.1 frystyk 721: {
722: BOOL found = NO;
723: if (dest && dest->source && dest != dest->source) {
724: HTRequest *src = dest->source;
725: if (src->mainDestination == dest) {
726: src->output_stream = NULL;
727: if (dest->input_stream)
728: (*dest->input_stream->isa->_free)(dest->input_stream);
729: found = YES;
730: } else if (src->destinations) {
731:
732: /* LOOK THROUGH THE LIST AND FIND THE RIGHT ONE */
733:
734: }
735: if (found) {
736: src->destStreams--;
737: if (STREAM_TRACE)
2.10 frystyk 738: TTYPrint(TDEST, "Destination. Unlinked %p from source %p\n",
2.1 frystyk 739: dest, src);
740: return YES;
741: }
742: }
743: return NO;
744: }
745:
746: /*
747: ** Removes all request structures in this PostWeb.
748: */
2.3 frystyk 749: PUBLIC BOOL HTRequest_removePostWeb (HTRequest *me)
2.1 frystyk 750: {
751: if (me && me->source) {
752: HTRequest *source = me->source;
753:
754: /* Kill main destination */
755: if (source->mainDestination)
756: HTRequest_removeDestination(source->mainDestination);
757:
758: /* Kill all other destinations */
759: if (source->destinations) {
760: HTList *cur = source->destinations;
761: HTRequest *pres;
762: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
763: HTRequest_removeDestination(pres);
764: }
765:
766: /* Remove source request */
767: HTRequest_removeDestination(source);
768: return YES;
769: }
770: return NO;
771: }
772:
773: /*
774: ** Kills all threads in a POST WEB connected to this request but
775: ** keep the request structures.
776: ** Some requests might be preemtive, for example a SMTP request (when
777: ** that has been implemented). However, this will be handled internally
778: ** in the load function.
779: */
2.3 frystyk 780: PUBLIC BOOL HTRequest_killPostWeb (HTRequest *me)
2.1 frystyk 781: {
782: if (me && me->source) {
783: HTRequest *source = me->source;
784:
785: /* Kill main destination */
786: if (source->mainDestination)
787: HTNet_kill(source->mainDestination->net);
788:
789: /* Kill all other destinations */
790: if (source->destinations) {
791: HTList *cur = source->destinations;
792: HTRequest *pres;
793: while ((pres = (HTRequest *) HTList_nextObject(cur)) != NULL)
794: HTNet_kill(pres->net);
795: }
796: /*
797: ** Kill source. The stream tree is now freed so we have to build
798: ** that again. This is done in HTRequest_linkDestination()
799: */
800: HTNet_kill(source->net);
801: source->output_stream = NULL;
802: return YES;
803: }
804: return NO;
805: }
806:
807: /* --------------------------------------------------------------------------*/
808: /* Physical Anchor Address Manager */
809: /* --------------------------------------------------------------------------*/
2.16 frystyk 810: #if 0
2.1 frystyk 811: /* Find physical name and access protocol
812: ** --------------------------------------
813: **
814: ** Checks for Cache, proxy, and gateway (in that order)
815: **
816: ** On exit,
817: ** returns HT_NO_ACCESS no protocol module found
818: ** HT_FORBIDDEN Error has occured.
819: ** HT_OK Success
820: **
821: */
822: PRIVATE int get_physical (HTRequest *req)
823: {
824: char * addr = HTAnchor_address((HTAnchor*)req->anchor); /* free me */
2.14 frystyk 825: HTList *list = HTRule_global();
826: char * physical = HTRule_translate(list, addr, NO);
827: if (!physical) {
828: free(addr);
829: return HT_FORBIDDEN;
2.1 frystyk 830: }
2.14 frystyk 831: HTAnchor_setPhysical(req->anchor, physical);
832: free(physical);
2.1 frystyk 833:
834: /*
835: ** Check local Disk Cache (if we are not forced to reload), then
836: ** for proxy, and finally gateways
837: */
838: {
839: char *newaddr=NULL;
840: if (req->reload != HT_FORCE_RELOAD &&
841: (newaddr = HTCache_getReference(addr))) {
842: if (req->reload != HT_CACHE_REFRESH) {
843: HTAnchor_setPhysical(req->anchor, newaddr);
844: HTAnchor_setCacheHit(req->anchor, YES);
845: } else { /* If refresh version in file cache */
846: req->RequestMask |= (HT_IMS + HT_NO_CACHE);
847: }
2.8 frystyk 848: } else if ((newaddr = HTProxy_find(addr))) {
2.1 frystyk 849: StrAllocCat(newaddr, addr);
850: req->using_proxy = YES;
851: HTAnchor_setPhysical(req->anchor, newaddr);
2.8 frystyk 852: } else if ((newaddr = HTGateway_find(addr))) {
2.1 frystyk 853: char * path = HTParse(addr, "",
854: PARSE_HOST + PARSE_PATH + PARSE_PUNCTUATION);
855: /* Chop leading / off to make host into part of path */
856: char * gatewayed = HTParse(path+1, newaddr, PARSE_ALL);
857: HTAnchor_setPhysical(req->anchor, gatewayed);
858: free(path);
859: free(gatewayed);
860: } else {
861: req->using_proxy = NO; /* We don't use proxy or gateway */
862: }
863: FREE(newaddr);
864: }
865: FREE(addr);
866:
867: /* Set the access scheme on our way out */
2.12 frystyk 868: return (HTProtocol_find(req, req->anchor)==YES) ? HT_OK : HT_NO_ACCESS;
2.1 frystyk 869: }
2.16 frystyk 870: #endif
2.1 frystyk 871:
872: /* --------------------------------------------------------------------------*/
873: /* Document Loader */
874: /* --------------------------------------------------------------------------*/
875:
876: /* Request a resource
877: ** ------------------
878: ** This is an internal routine, which has an address AND a matching
879: ** anchor. (The public routines are called with one OR the other.)
880: ** Returns:
881: ** YES if request has been registered (success)
882: ** NO an error occured
883: */
2.9 frystyk 884: PUBLIC BOOL HTLoad (HTRequest * request, BOOL recursive)
2.1 frystyk 885: {
886: if (!request || !request->anchor) {
2.10 frystyk 887: if (PROT_TRACE) TTYPrint(TDEST, "Load Start.. Bad argument\n");
2.1 frystyk 888: return NO;
889: }
2.14 frystyk 890: if (request->method == METHOD_INVALID) request->method = METHOD_GET;
2.16 frystyk 891: if (!recursive && request->error_stack) {
892: HTError_deleteAll(request->error_stack);
893: request->error_stack = NULL;
894: }
2.18 frystyk 895: return HTNet_newClient(request);
2.1 frystyk 896: }
897:
2.18 frystyk 898: /* Serv a resource
899: ** ---------------
900: ** This function initiates the server side of a request and starts
901: ** serving it back accross the network.
902: ** Returns:
903: ** YES if request has been registered (success)
904: ** NO an error occured
905: */
2.20 frystyk 906: PUBLIC BOOL HTServ (HTRequest * request, SOCKET master, BOOL recursive)
2.18 frystyk 907: {
908: if (!request || !request->access) {
909: if (PROT_TRACE) TTYPrint(TDEST, "Serv Start.. Bad argument\n");
910: return NO;
911: }
912: if (!recursive && request->error_stack) {
913: HTError_deleteAll(request->error_stack);
914: request->error_stack = NULL;
915: }
2.20 frystyk 916: return HTNet_newServer(request, master);
2.14 frystyk 917: }
Webmaster