1 /*
2 
3   					W3C Sample Code Library libwww HTNet Class
4 
5 
6 !
7   The Net Class
8 !
9 */
10 
11 /*
12 **	(c) COPYRIGHT MIT 1995.
13 **	Please first read the full copyright statement in the file COPYRIGH.
14 */
15 
16 /*
17 
18 The Net class manages information related to a "thread" in libwww. As libwww
19 threads are not really threads but a notion of using interleaved, non-blocking
20 I/O for accessing data objects from the network (or local file system), they
21 can be used on any platform with or without support for native threads. In
22 the case where you have an application using real threads the Net class is
23 simply a object maintaining links to all other objects involved in serving
24 the request. If you are using the libwww pseudo threads then the Net object
25 contains enough information to stop and start a request based on which BSD
26 sockets are ready. In practise this is of course transparent to the application
27 - this is just to explain the difference.
28 
29 When a Request object is passed to the Library ,
30 the core creates a new HTNet object per channel
31 used by the request. In many cases a request only uses a single
32 channel object but, for example, FTP requests use
33 at least two - one for the control connection and one for the data connection.
34 
35 You can find more information about the libwww pseudo thread model in the
36  Multithread Specifications.
37 
38 This module is implemented by HTNet.c, and it is a
39 part of the W3C Sample Code Library.
40 */
41 
42 #ifndef HTNET_H
43 #define HTNET_H
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 /*
50 
51 The HTNet object is the core of the request queue management.
52 This object contains information about the socket descriptor, the input read
53 buffer etc. required to identify and service a request.
54 */
55 
56 typedef struct _HTNet HTNet;
57 
58 #include "HTEvent.h"
59 #include "HTReq.h"
60 #include "HTResponse.h"
61 #include "HTTrans.h"
62 #include "HTHost.h"
63 #include "HTProt.h"
64 #include "HTChannl.h"
65 #include "HTDNS.h"
66 
67 /*
68 .
69   Generic BEFORE and AFTER Filter Management
70 .
71 
72 Filter functions can be registered to be called before and
73 after a request has either been started or has terminated. The
74 conditions for BEFORE and AFTER filters are not the same, and so
75 we maintain them independently. Filters can be registered globally or locally.
76 The global filters are registered directly by the Net Object (this module)
77 and the local filters are registered by the
78 HTRequest Object. However, both  local and
79 global filters use the same regisration mechanism which we provide here.
80 (
81   Filter Ordering
82 )
83 
84 Filters can be registered by anyone and as they are an often used mechanism
85 for introducing extensions in libwww, they are videly used to handle
86 authentication, redirection, etc. Many filters can be registered at once
87 and not all of the filters may know about the other filters. Therefore, it
88 is difficult to specify an absolute ordering by which the filters should
89 be called. Instead you can decide a relative order by which the filters should
90 be called. The order works pretty much like the Unix priority mechanism running
91 from HT_FILTER_FIRST to HT_FILTER_LAST having
92 HT_FILTER_MIDDLE being the "normal" case.
93 */
94 
95 typedef enum _HTFilterOrder {
96     HT_FILTER_FIRST	= 0x0,		/*     0 */
97     HT_FILTER_EARLY	= 0x3FFF,	/* 16383 */
98     HT_FILTER_MIDDLE	= 0x7FFF,	/* 32767 */
99     HT_FILTER_LATE	= 0xBFFE,	/* 49150 */
100     HT_FILTER_LAST	= 0xFFFF	/* 65535 */
101 } HTFilterOrder;
102 
103 /*
104 
105 In case multiple filters are registered with the same order then they are
106 called in the inverse order they were registered. 
107 (
108   Filter URL Templates
109 )
110 
111 Both BEFORE and AFTER filters can be registered with a URL
112 template in which case they are only called when the Request URL
113 matches the template. A template is simply a string which is matched against
114 the Request URL. The string can be terminated by a single
115 "*" in which case all strings matching the template up til the
116 "*" is considered a match. A template can be as short as the access scheme
117 which enmables a filter for a specific access method only, for example
118 "http//<star>".
119 (
120   BEFORE Filters
121 )
122 
123 A BEFORE filter is called whenever we issue a request and they have
124 been selected by the execution procedure. BEFORE filters are registered
125 with a context and a filter order by which they are to be called
126 and a URL template which may be NULL. In this case, the filter is
127 called on every request. The mode can be used by anybody to pass an extra
128 parameter to a filter. This is not really OO thinking - but hey - this is
129 C ;-)
130 */
131 typedef int HTNetBefore (HTRequest * request, void * param, int mode);
132 
133 /*
134 
135 You can add a BEFORE filter in the list provided by the caller. Several
136 filters can be registered in which case they are called with the filter ordering
137 in mind.
138 */
139 
140 extern BOOL HTNetCall_addBefore (HTList * list, HTNetBefore * before,
141 				 const char * tmplate, void * param,
142                                  HTFilterOrder order);
143 
144 /*
145 
146 You can also unregister all instances of a BEFORE filter from a list using
147 the following function
148 */
149 
150 extern BOOL HTNetCall_deleteBefore (HTList * list, HTNetBefore * before);
151 
152 /*
153 
154 You get rid of all BEFORE filters using this function
155 */
156 
157 extern BOOL HTNetCall_deleteBeforeAll (HTList * list);
158 
159 /*
160 
161 The BEFORE filters are expected and called if appropriate every time we issue
162 a new request. Libwww calls the BEFORE filters in the order specified at
163 registration time. If a filter returns other than HT_OK then stop and return
164 immediately. Otherwise return what the last filter returns.
165 */
166 
167 extern int HTNetCall_executeBefore (HTList * list, HTRequest * request);
168 
169 /*
170 (
171   AFTER Filters
172 )
173 
174 An AFTER filter is called whenever we have terminated a request. That
175 is, on the way out from the protocol module and
176 back to the application. AFTER filters are registered with a
177 context, a status, a filter order by which they are
178 to be called and a URL template which may be NULL. The status of the
179 request may determine which filter to call. The set of possible values are
180 given below. An AFTER filter can be registered to handle one or more
181 of the codes.
182 
183 
184     HT_ERROR
185 
186     An error occured
187 
188     HT_LOADED
189 
190     The document was loaded
191 
192     HT_NO_DATA
193 
194     OK, but no data
195 
196     HT_NO_ACCESS
197 
198     The request could not be succeeded due to lack of credentials
199 
200     HT_NO_PROXY_ACCESS
201 
202     The request could not be succeeded due to lack of credentials for accessing
203     an intermediate proxy
204 
205     HT_RETRY
206 
207     Retry request after at a later time
208 
209     HT_PERM_REDIRECT
210 
211     The request has been permanently redirected and we send back the new URL
212 
213     HT_TEMP_REDIRECT
214 
215     The request has been temporarily redirected and we send back the new URL
216 
217     HT_ALL
218 
219     All of above
220 
221 
222 A Protocol module can also, in certain cases, return a HT_IGNORE
223 in which case no filters are called
224 */
225 
226 typedef int HTNetAfter (HTRequest * request, HTResponse * response,
227                         void * param, int status);
228 
229 /*
230 
231 You can register a AFTER filter in the list provided by the caller. Several
232 filters can be registered in which case they are called with the filter ordering
233 in mind.
234 */
235 
236 extern BOOL HTNetCall_addAfter (HTList * list, HTNetAfter * after,
237 				const char * tmplate, void * param,
238 				int status, HTFilterOrder order);
239 
240 /*
241 
242 You can either unregister all filters registered for a given status using
243 this function or the filter for all status codes.
244 */
245 
246 extern BOOL HTNetCall_deleteAfter (HTList * list, HTNetAfter * after);
247 extern BOOL HTNetCall_deleteAfterStatus (HTList * list, int status);
248 
249 /*
250 
251 You can also delete all AFTER filters in list
252 */
253 
254 extern BOOL HTNetCall_deleteAfterAll (HTList * list);
255 
256 /*
257 
258 This function calls all the AFTER filters in the order specified at registration
259 time and if it has the right status code and it's not HT_IGNORE.
260 We also check for any template and whether it matches or not. If a filter
261 returns other than HT_OK then stop and return immediately. Otherwise return
262 what the last filter returns.
263 */
264 
265 extern int HTNetCall_executeAfter (HTList * list, HTRequest * request,
266 				   int status);
267 
268 /*
269 .
270   Global BEFORE and AFTER Filter Management
271 .
272 
273 Global filters are inspected on every request (they do not have to be called
274 - only if the conditions match). You can also register filters locally in
275 the Request object.
276 
277   Global BEFORE Filters
278 
279 
280 These are the methods to handle global BEFORE Filters.
281 */
282 
283 extern BOOL HTNet_setBefore (HTList * list);
284 
285 extern HTList * HTNet_before (void);
286 
287 extern BOOL HTNet_addBefore (HTNetBefore * before, const char * tmplate,
288 			     void * param, HTFilterOrder order);
289 
290 extern BOOL HTNet_deleteBefore (HTNetBefore * before);
291 
292 /*
293 
294 You can call both the local and the global BEFORE filters (if any)
295 */
296 
297 extern int HTNet_executeBeforeAll (HTRequest * request);
298 
299 /*
300 
301   Global AFTER Filters
302 
303 
304 These are the methods to handle global AFTER Filters.
305 */
306 
307 extern BOOL HTNet_setAfter (HTList * list);
308 
309 extern HTList * HTNet_after (void);
310 
311 extern BOOL HTNet_addAfter (HTNetAfter * after, const char * tmplate,
312 			    void * param, int status,
313                             HTFilterOrder order);
314 
315 extern BOOL HTNet_deleteAfter (HTNetAfter * after);
316 
317 extern BOOL HTNet_deleteAfterStatus (int status);
318 
319 /*
320 
321 You can call both the local and the global AFTER filters (if any)
322 */
323 
324 extern int HTNet_executeAfterAll (HTRequest * request, int status);
325 
326 /*
327 .
328   Socket Resource Management
329 .
330 
331 The request queue ensures that no more than a fixed number of TCP connections
332 are open at the same time. If more requests are handed to the Library, they
333 are put into the pending queue and initiated when sockets become free.
334 (
335   Number of Simultanous open TCP connections
336 )
337 
338 Set the max number of simultanous sockets. The default value is HT_MAX_SOCKETS
339 which is 6. The number of persistent connections depend on this value as
340 a deadlock can occur if all available sockets a persistent (see the
341 DNS Manager for more information on setting the
342 number of persistent connections). The number of persistent connections can
343 never be more than the max number of sockets-2, so letting newmax=2 prevents
344 persistent sockets.
345 */
346 
347 extern BOOL HTNet_setMaxSocket (int newmax);
348 extern int  HTNet_maxSocket (void);
349 
350 /*
351 (
352   Socket Counters
353 )
354 */
355 
356 extern void HTNet_increaseSocket (void);
357 extern void HTNet_decreaseSocket (void);
358 
359 extern int HTNet_availableSockets (void);
360 
361 /*
362 (
363   Persistent Socket Counters
364 )
365 */
366 
367 extern void HTNet_increasePersistentSocket (void);
368 extern void HTNet_decreasePersistentSocket (void);
369 
370 extern int HTNet_availablePersistentSockets (void);
371 
372 /*
373 (
374   Any Ongoing Connections?
375 )
376 
377 Returns whether there are active requests. Idle persistent sockets do not
378 count as active.
379 */
380 
381 extern BOOL HTNet_isIdle (void);
382 
383 /*
384 (
385   List Active Queue
386 )
387 
388 Returns the list of active requests that are currently having an open connection.
389 Returns list of HTNet objects or NULL if error.
390 */
391 
392 extern HTList *HTNet_activeQueue (void);
393 extern BOOL HTNet_idle (void);
394 
395 /*
396 (
397   Are we Active?
398 )
399 
400 We have some small functions that tell whether there are registered requests
401 in the Net manager. There are tree queues: The active, the
402 pending, and the persistent. The active queue
403 is the set of requests that are actively sending or receiving data. The
404 pending is the requests that we have registered but which are waiting
405 for a free socket. The Persistent queue are requets that are waiting
406 to use the same socket in order to save network resoures (if the server
407 understands persistent connections).
408 
409   Active Requests?
410 
411 
412 Returns whether there are requests in the active queue or not
413 */
414 
415 extern BOOL HTNet_idle (void);
416 
417 /*
418 
419   Registered Requests?
420 
421 
422 Returns whether there are requests registered in any of the lists or not
423 */
424 
425 extern BOOL HTNet_isEmpty (void);
426 extern int HTNet_count (void);
427 
428 /*
429 (
430   List Pending Queue
431 )
432 
433 Returns the list of pending requests that are waiting to become active. Returns
434 list of HTNet objects or NULL if error
435 */
436 
437 extern HTList *HTNet_pendingQueue (void);
438 
439 /*
440 .
441   Creation and Deletion Methods
442 .
443 
444 The Net object is intended to live as long as the request is still active.
445 In that regard it is very similar to the Request Object
446 . However, the main difference is that a Net object represents a "thread"
447 in the Library and a request may have multiple "threads" - an example is
448 a FTP request which has a thread to handle the control connection and one
449 to handle the data connections.
450 (
451   Create a new Object
452 )
453 
454 If we have more than HTMaxActive connections already then put this into the
455 pending queue, else start the request by calling the call back function
456 registered with this access method. Returns YES if OK, else NO
457 */
458 
459 extern BOOL HTNet_newClient (HTRequest * request);
460 
461 /*
462 
463 You can create a new HTNet object as a new request to be handled. If we have
464 more than HTMaxActive connections already then return NO. Returns YES if
465 OK, else NO
466 */
467 
468 extern BOOL HTNet_newServer (HTRequest * request);
469 
470 /*
471 
472 And you can create a plain new HTNet object using the following method:
473 */
474 
475 extern HTNet * HTNet_new (HTHost * host);
476 
477 /*
478 (
479   Duplicate an existing Object
480 )
481 
482 Creates a new HTNet object as a duplicate of the same request. Returns YES
483 if OK, else NO.
484 */
485 
486 extern HTNet * HTNet_dup (HTNet * src);
487 extern BOOL HTNet_deleteDup (HTNet * dup);
488 
489 /*
490 (
491   Launch a Net Object
492 )
493 
494 Start a Net obejct by calling the protocol module.
495 */
496 extern BOOL HTNet_start (HTNet * net);
497 
498 /*
499 (
500   Call a Net Event Handler
501 )
502 
503 This functions lets the caller play event manager as it can calls any event
504 handler with the event type and context passed to the function
505 */
506 
507 extern BOOL HTNet_execute (HTNet * net, HTEventType type);
508 
509 extern HTEvent * HTNet_event (HTNet * net);
510 extern BOOL HTNet_setEventParam (HTNet * net, void * eventParam);
511 extern void * HTNet_eventParam (HTNet * net);
512 extern BOOL HTNet_setEventCallback(HTNet * net, HTEventCallback * cbf);
513 extern HTEventCallback * HTNet_eventCallback(HTNet * net);
514 
515 /*
516 (
517   Delete an Object
518 )
519 
520 Deletes the HTNet object from the list of active requests and calls any
521 registered call back functions IF not the status is HT_IGNORE. This is used
522 if we have internal requests that the app doesn't know about. We also see
523 if we have pending requests that can be started up now when we have a socket
524 free. The filters are called in the reverse order of which they were registered
525 (last one first);
526 */
527 
528 extern BOOL HTNet_delete (HTNet * me, int status);
529 
530 /*
531 (
532   Delete ALL HTNet Objects
533 )
534 
535 Deletes all HTNet object that might either be active or pending We DO NOT
536 call the call back functions - A crude way of saying goodbye!
537 */
538 
539 extern BOOL HTNet_deleteAll (void);
540 
541 /*
542 .
543   Net Class Methods
544 .
545 (
546   Make an Object Wait
547 )
548 
549 Let a net object wait for a persistent socket. It will be launched from the
550 HTNet_delete() function when the socket gets free.
551 */
552 
553 extern BOOL HTNet_wait (HTNet *net);
554 
555 /*
556 (
557   Priority Management
558 )
559 
560 Each HTNet object is created with a priority which it inherits from the
561 Request manager. However, in some stuations it is
562 useful to be to change the current priority after the request has been started.
563 These two functions allow you to do this. The effect will show up the first
564 time (which might be imidiately) the socket blocks and control returns to
565 the event loop. Also have a look at how you can do this before the request
566 is issued in the request manager.
567 */
568 
569 extern HTPriority HTNet_priority (HTNet * net);
570 extern BOOL HTNet_setPriority (HTNet * net, HTPriority priority);
571 
572 /*
573 (
574   Persistent Connections
575 )
576 
577 You can set a Net object to handle persistent connections for example using
578 HTTP, NNTP, or FTP. You can control whether a Net object supports persistent
579 connections or not using this function.
580 */
581 
582 extern BOOL HTNet_persistent (HTNet * net);
583 
584 /*
585 
586 You can set or disable a Net object supporting persistent connections using
587 this function:
588 */
589 
590 extern BOOL HTNet_setPersistent (HTNet *           net,
591                                  BOOL              persistent,
592                                  HTTransportMode   mode);
593 
594 /*
595 (
596   Kill one or more Requests
597 )
598 
599   Kill this request and all requests in the Pipeline
600 
601 
602 When pipelining, it is not possible to kill a single request as we then loose
603 track of where we are in the pipe. It is therefore necessary to kill the
604 whole pipeline.
605 */
606 
607 extern BOOL HTNet_killPipe (HTNet * net);
608 
609 /*
610 
611   Kill a single Request
612 
613 
614 This is not often used anymore, consider using the pipeline version above.
615 Kill the request by calling the call back function with a request for closing
616 the connection. Does not remove the object. This is done by HTNet_delete()
617 function which is called by the load routine. Returns OK if success, NO on
618 error.
619 */
620 
621 extern BOOL HTNet_kill (HTNet * me);
622 
623 /*
624 
625   Kill ALL Requests
626 
627 
628 Kills all registered (active as well as pending) requests by calling
629 the call back function with a request for closing the connection. We do not
630 remove the HTNet object as it is done by HTNet_delete(). Returns OK if success,
631 NO on error
632 */
633 
634 extern BOOL HTNet_killAll (void);
635 
636 /*
637 (
638   Create Input and Output Streams
639 )
640 
641 You create the input stream and bind it to the channel using the following
642 methods. Please read the description in the
643 HTIOStream module on the parameters
644 target, param, and mode. Both methods return YES
645 if OK, else NO.
646 */
647 
648 #if 0
649 extern HTInputStream * HTNet_getInput (HTNet * net, HTStream * target,
650 				       void * param, int mode);
651 #endif
652 extern HTOutputStream * HTNet_getOutput (HTNet * me, void * param, int mode);
653 
654 /*
655 (
656   Net Context Descriptor
657 )
658 
659 Just like the request
660 object, a net object can be assigned a context which keeps track of context
661 dependent information. The Library does not use this information nor does
662 it depend on it but it allows the application to customize a net object to
663 specific uses.
664 */
665 extern BOOL HTNet_setContext (HTNet * net, void * context);
666 extern void * HTNet_context (HTNet * net);
667 
668 /*
669 (
670   Socket Descriptor
671 )
672 */
673 
674 extern BOOL HTNet_setSocket (HTNet * net, SOCKET sockfd);
675 extern SOCKET HTNet_socket (HTNet * net);
676 
677 /*
678 (
679   Preemptive or Non-preemptive Access
680 )
681 
682 A access scheme is defined with a default for using either preemptive (blocking
683 I/O) or non-premitve (non-blocking I/O). This is basically a result of the
684 implementation of the protocol module itself. However, if non-blocking I/O
685 is the default then some times it is nice to be able to set the mode to blocking
686 instead. For example when loading the first document (the home page) then
687 blocking can be used instead of non-blocking.
688 */
689 
690 extern BOOL HTNet_preemptive (HTNet * net);
691 
692 /*
693 (
694   The Request Object
695 )
696 
697 The Request object is normally set up automatically
698 but can be changed at a later time.
699 */
700 
701 extern BOOL HTNet_setRequest (HTNet * net, HTRequest * request);
702 extern HTRequest * HTNet_request (HTNet * net);
703 
704 /*
705 (
706   The Protocol Object
707 )
708 */
709 
710 extern BOOL HTNet_setProtocol (HTNet * net, HTProtocol * protocol);
711 extern HTProtocol * HTNet_protocol (HTNet * net);
712 
713 /*
714 (
715   The Transport Object
716 )
717 
718 The transport object is normally set up automatically
719 but can be changed at a later time.
720 */
721 
722 extern BOOL HTNet_setTransport (HTNet * net, HTTransport * tp);
723 extern HTTransport * HTNet_transport (HTNet * net);
724 
725 /*
726 (
727   The Channel Object
728 )
729 */
730 
731 extern BOOL HTNet_setChannel (HTNet * net, HTChannel * channel);
732 extern HTChannel * HTNet_channel (HTNet * net);
733 
734 /*
735 (
736   The Host Object
737 )
738 */
739 
740 extern BOOL HTNet_setHost (HTNet * net, HTHost * host);
741 extern HTHost * HTNet_host (HTNet * net);
742 
743 /*
744 (
745   The DNS Object
746 )
747 
748 The DNS object keeps track of the DNS entries that we have already checked
749 out.
750 */
751 
752 extern BOOL HTNet_setDns (HTNet * net, HTdns * dns);
753 extern HTdns * HTNet_dns (HTNet * net);
754 
755 /*
756 (
757   Target for Input Read Stream
758 )
759 */
760 
761 extern HTStream * HTNet_readStream(HTNet * net);
762 extern BOOL HTNet_setReadStream (HTNet * net, HTStream * stream);
763 
764 /*
765 (
766   Should we count Raw bytes?
767 )
768 
769 This functions can be used to determine whether bytes count should be managed
770 at the low level read stream or at a higher level. If the data transfer equals
771 the lifetime of a single document like for example in FTP or HTTP/1.0 then
772 this may be a reasonable thing to do.
773 */
774 extern BOOL HTNet_setRawBytesCount (HTNet * net, BOOL mode);
775 extern BOOL HTNet_rawBytesCount (HTNet * net);
776 
777 /*
778 */
779 
780 #ifdef __cplusplus
781 }
782 #endif
783 
784 #endif /* HTNET_H */
785 
786 /*
787 
788 
789 
790   @(#) $Id$
791 
792 */
793