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