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