/*                                                  W3C Sample Code Library libwww Host Class
                                      THE HOST CLASS
                                             
 */
/*
**      (c) COPYRIGHT MIT 1995.
**      Please first read the full copyright statement in the file COPYRIGH.
*/
/*

   The Host class manages what we know about a remote host. This can for example be what
   type of host it is, and what version it is using. Notice that a host object can be used
   to describe both a server or a client - all information in the Host object can be
   shared regardless of whether it is to be used in a server application or a client
   application.
   
   This module is implemented by HTHost.c, and it is a part of the W3C Sample Code
   Library.
   
 */
#ifndef HTHOST_H
#define HTHOST_H

typedef struct _HTHost HTHost;
#define HOST_HASH_SIZE          67

#include "HTChannl.h"
#include "HTReq.h"
#include "HTEvent.h"
#include "HTProt.h"
#include "HTTimer.h"
/*

   The Host class contains information about the remote host, for example the type
   (HTTP/1.0, HTTP/1.1, FTP etc.) along with information on how the connections can be
   used (if it supports persistent connections, interleaved access etc.)
   
CREATION AND DELETION METHODS

   We keep a cache of information that we know about a remote host. This allows us to be
   much more detailed in generating requests. Search the host info cache for a host object
   or create a new one and add it. Examples of host names are
   
      www.w3.org
      
      www.foo.com:8000
      
  Add a Host Object
  
 */
extern HTHost * HTHost_new (char * host, u_short u_port);
extern HTHost * HTHost_newWParse(HTRequest * request, char * url, u_short u_port);
extern int HTHost_hash (HTHost * host);
/*

  Delete a Host Object
  
   The Host Class contains an automatic garbage collection of Host objects so that we
   don't keep information around that is stale.
   
  Find a Host Object
  
   Searches the cache of known hosts to see if we already have information about this
   host. If not then we return NULL.
   
 */
extern HTHost * HTHost_find (char * host);
/*

REMOTE HOST INFORMATION

   We keep track of the capabilities of the host in the other end so thatwe may adjust our
   queries to fit it better
   
  Remote Host Name
  
   Get the name of the remote host. This is set automatically when a new Host object and
   can be asked for at any point in time. You can not change the host name but must create
   a new Host object instead.
   
 */
extern char * HTHost_name       (HTHost * host);
/*

  Remote Host Protocol Class and Version
  
   Define the host class of the host at the other end. A class is a generic description of
   the protocol which is exactly like the access method in a URL, for example "http" etc.
   The host version is a finer distinction (sub-class) between various versions of the
   host class, for example HTTP/0.9, HTTP/1.1 etc. The host version is a bit flag that the
   protocol module can define on its own. That way we don't have to change this module
   when registering a new protocol module. The host type is a description of whether we
   can keep the connection persistent or not.
   
 */
extern char * HTHost_class      (HTHost * host);
extern void HTHost_setClass     (HTHost * host, char * s_class);

extern int  HTHost_version      (HTHost * host);
extern void HTHost_setVersion   (HTHost * host, int version);
/*

  Public Methods accessible on This Host
  
   A server can inform a client about the supported methods using the Public header.
   
 */
extern HTMethod HTHost_publicMethods    (HTHost * me);
extern void HTHost_setPublicMethods     (HTHost * me, HTMethod methodset);
extern void HTHost_appendPublicMethods  (HTHost * me, HTMethod methodset);
/*

  Server Name of Remote Host
  
   A server can send its server application name and version in a HTTP response. We pick
   up this information and add it to the Host object
   
 */
extern char * HTHost_server     (HTHost * host);
extern BOOL HTHost_setServer    (HTHost * host, const char * server);
/*

  User Agent Name of Remote Host
  
   A client can send the name of the client application in a HTTP request. We pick up this
   information and add it to the Host Object
   
 */
extern char * HTHost_userAgent  (HTHost * host);
extern BOOL HTHost_setUserAgent (HTHost * host, const char * userAgent);
/*

  Range Units Accepted by this Host
  
   Since all HTTP entities are represented in HTTP messages as sequences of bytes, the
   concept of a byte range is meaningful for any HTTP entity. (However, not all clients
   and servers need to support byte-range operations.) Byte range specifications in HTTP
   apply to the sequence of bytes in the entity-body (not necessarily the same as the
   message-body). A byte range operation may specify a single range of bytes, or a set of
   ranges within a single entity.
   
   You can also check whether a specific range unit is OK. We always say YES except if we
   have a specific statement from the server that it doesn't understand byte ranges - that
   is - it has sent "none" in a "Accept-Range" response header
   
 */
extern char * HTHost_rangeUnits  (HTHost * host);
extern BOOL HTHost_setRangeUnits (HTHost * host, const char * units);
extern BOOL HTHost_isRangeUnitAcceptable (HTHost * host, const char * unit);
/*

PERSISTENT CONNECTIONS

   We don't want more than MaxSockets-2 connections to be persistent in order to avoid
   deadlock.
   
 */
extern BOOL HTHost_setPersistent (HTHost * host, BOOL persistent,
                                  HTTransportMode mode);
extern BOOL HTHost_clearChannel (HTHost * host, int status);

extern HTChannel * HTHost_channel (HTHost * host);
/*

  Is this host Persistent?
  
   Check whether we have a persistent channel or not
   
 */
extern BOOL HTHost_isPersistent (HTHost * host);
extern BOOL HTHost_setCloseNotification (HTHost * host, BOOL mode);
extern BOOL HTHost_closeNotification (HTHost * host);
/*

  Timing Persistent Channels
  
   Normally we wait for the peer process to close persistent connections but in order not
   to use up our own resources, we have a timeout on our own. The default value is 1 hour,
   but you can modify the value using the following methods:
   
 */
extern time_t HTHost_persistTimeout (time_t timeout);
extern void HTHost_setPersistTimeout (time_t timeout);
/*

   Each persistent connection has an absolute value of when this connection most likely
   will expire. If the peer process does not inform us, we use our own timeout.
   
 */
extern void HTHost_setPersistExpires (HTHost * host, time_t expires);
extern time_t HTHost_persistExpires (HTHost * host);
extern void HTHost_setReqsPerConnection (HTHost * host, int reqs);
extern int HTHost_reqsPerConnection (HTHost * host);
extern void HTHost_setReqsMade (HTHost * host, int reqs);
extern int HTHost_reqsMade (HTHost * host);
/*

TRANSPORT MODE

   Handle the connection mode. The mode may change mode in the middle of a connection If
   the new mode is lower than the old mode then adjust the pipeline accordingly. That is,
   if we are going into single mode then move all entries in the pipeline and move the
   rest to the pending queue. They will get launched at a later point in time.
   
 */
extern HTTransportMode HTHost_mode (HTHost * host, BOOL * active);
extern BOOL HTHost_setMode (HTHost * host, HTTransportMode mode);
/*

QUEUING REQUESTS

   Requests are queued in the Host object until we have resources to start them. The
   request is in the form of a Net object as we may have multiple socket requests per
   Request object. This is for example the case with FTP which uses two connections.
   
 */
extern int HTHost_addNet     (HTHost * host, HTNet * net);
extern BOOL HTHost_free      (HTHost * host, int status);
extern BOOL HTHost_deleteNet (HTHost * host, HTNet * net);
extern HTList * HTHost_net   (HTHost * host);
/*

  Is the Host Idle?
  
   Before we can start a new connection to the host we must be sure that the host is idle.
   That is, if it can accept a new connection. We have several modes describing how and
   when a host is idle. This is a function of the Transport Object
   
 */
extern BOOL HTHost_isIdle (HTHost * host);
/*

  Handling Pending Requests
  
   There are two ways we can end up with pending reqyests:
   
      If we are out of sockets then register new host objects as pending.
      
      If we are pending on a connection then register new net objects as pending
      
   This set of functions handles pending host objects and can start new requests as
   resources get available. The first function checks the host object for any pending Net
   objects and return the first of these Net objects.
   
 */
extern HTNet * HTHost_nextPendingNet (HTHost * host);
/*

   The second checks the list of pending host objects waiting for a socket and returns the
   first of these Host objects.
   
 */
extern HTHost * HTHost_nextPendingHost (void);
/*

   Start the next pending request if any. First we look for pending requests for the same
   host and then we check for any other pending hosts. If nothing pending then register a
   catch close event handler to have something catching the socket if the remote server
   closes the connection, for example due to timeout.
   
 */
extern BOOL HTHost_launchPending (HTHost * host);

extern int HTHost_connect (HTHost * host, HTNet * net, char * url,
                           HTProtocolId port);
/*

   HTHost clients can use the host for all IO and take advantage of host multiplexing and
   pipelining.
   
EVENT MANAGEMENT

 */
extern int HTHost_register(HTHost * host, HTNet * net, HTEventType type);
extern int HTHost_unregister(HTHost * host, HTNet * net, HTEventType type);
extern int HTHost_tickleFirstNet(HTHost * host, HTEventType type);
extern BOOL HTHost_setRemainingRead(HTHost * host, size_t remainaing);
extern SockA * HTHost_getSockAddr(HTHost * host);
/*

  Control the Delayed Flush Timer
  
   These methods can control how long we want to wait for a flush on a given host.
   
 */
extern BOOL HTHost_setWriteDelay (HTHost * host, ms_t delay);
extern ms_t HTHost_writeDelay (HTHost * host);
extern int HTHost_findWriteDelay(HTHost * host, ms_t lastFlushTime, int buffSize);
/*

   It is also possible to explicitly require a flush using the following method
   
 */
extern int HTHost_forceFlush(HTHost * host);
/*

   You can also set the global value so that all new host objects will inherit this value
   instead of setting it individually.
   
 */
extern BOOL HTHost_setDefaultWriteDelay (ms_t delay);
extern ms_t HTHost_defaultWriteDelay (void);
/*

  Event Timeouts
  
   Events can be assigned a timeout which causes the event to be triggered if the timeout
   happens before other action is available on the socket. You can assign a global timeout
   for all host object using the following methods
   
 */
extern int HTHost_eventTimeout (void);
extern void HTHost_setEventTimeout (int millis);
/*

  Get the Next Net object for Reading and Writing
  
 */
extern HTNet * HTHost_firstNet     (HTHost * host);
extern HTNet * HTHost_getReadNet  (HTHost * host);
extern HTNet * HTHost_getWriteNet (HTHost * host);
/*

  Automatic Connection Recovery
  
   In case a pipeline is broken then we have to recover it and start again. This is
   handled automatically by the host object
   
 */
extern BOOL HTHost_recoverPipe (HTHost * host);
/*

  Get input and output Streams for this Host
  
 */
extern HTInputStream * HTHost_getInput (HTHost * host, HTTransport * transport,
                                        void * param, int mode);

extern HTOutputStream * HTHost_getOutput (HTHost * host, HTTransport * tp,
                                          void * param, int mode);
/*

  The Channel Associated with this Host
  
 */
extern BOOL HTHost_setChannel (HTHost * host, HTChannel * channel);
extern HTChannel * HTHost_channel (HTHost * host);
/*

  Read Management
  
 */
extern int HTHost_read(HTHost * host, HTNet * net);
extern BOOL HTHost_setConsumed(HTHost * host, size_t bytes);
/*

MULTI HOMED HOST MANAGEMENT

   We also keep track of if a host has multiple IP addresses. If so then it is called a
   multi-homed host. This is used for two things: finding the fastest host with this name
   and as a backup if one or more of the hosts are down.
   
 */
extern BOOL HTHost_setHome (HTHost * host, int home);
extern int HTHost_home (HTHost * host);

extern BOOL HTHost_setRetry (HTHost * host, int retry);
extern int HTHost_retry (HTHost * host);
extern BOOL HTHost_decreaseRetry (HTHost * host);
/*

 */
#endif /* HTHOST_H */
/*

   
   ___________________________________
   
                            @(#) $Id: HTHost.html,v 2.15 1997/04/05 00:25:29 frystyk Exp $
                                                                                          
   */
