(* $Id: telnet_client.mli 459 2006-04-30 19:49:19Z gerd $
* ----------------------------------------------------------------------
*
*)
(** Telnet client
*
* This is a Telnet client providing the basic Telnet services. It
* supports sending and receiving data (asynchronously), and the
* negotiation of Telnet options, but it does not implement any option.
*)
exception Telnet_protocol of exn;;
(** Wrapper for exceptions that already passed the exception handler. *)
type telnet_command =
Telnet_data of string (** User data *)
| Telnet_nop (** No operation *)
| Telnet_dm (** data mark *)
| Telnet_brk (** break *)
| Telnet_ip (** interrupt process *)
| Telnet_ao (** abort output *)
| Telnet_ayt (** are you there? *)
| Telnet_ec (** erase character *)
| Telnet_el (** erase line *)
| Telnet_ga (** Go ahead *)
| Telnet_sb of char (** Begin of subnegotiation *)
| Telnet_se (** End of subnegotation *)
| Telnet_will of char (** Acknowledges that option is in effect *)
| Telnet_wont of char (** Acknowledges that option is rejected *)
| Telnet_do of char (** Requests to turn on an option *)
| Telnet_dont of char (** Requests to turn off an option *)
| Telnet_unknown of char (** Unknown command *)
| Telnet_eof (** End of file *)
| Telnet_timeout (** Timeout event *)
(** A [telnet_command] is the interpretation of the octets in a Telnet
* session, i.e. it is one level above the octet stream. See RFC 854
* for an explanation what the commands mean. [Telnet_data] represents
* the data chunks between the commands. Note that you do not need
* to double octets having value 255; this is done automatically.
* [Telnet_unknown] represents any command not covered by RFC 854, for
* example the End-of-record-mark (introduced in RFC 885) would be
* [Telnet_unknown '\239']. [Telnet_eof] represents the end of the octet
* stream, useable in both directions. [Telnet_timeout] is added to the
* input queue if I/O has not been happened for the configured period
* of time.
*)
type telnet_options =
{ connection_timeout : float;
verbose_connection : bool;
verbose_input : bool;
verbose_output : bool;
}
(** [telnet_options]: modifies the behaviour of the client. Do not mix these
* options up with the options negotiated with the remote side.
*
* - [connection_timeout]: After this period of time (in seconds) a
* [Telnet_timeout] pseudo-command is added to
* the input queue, and the connection is
* aborted.
* - [verbose_connection]: Enables printing of connection events to stderr.
* - [verbose_input]: Enables printing of input events to stderr.
* - [verbose_output]: Enables printing of output events to stderr.
*)
type telnet_negotiated_option =
Telnet_binary (** see RFC 856 *)
| Telnet_echo (** see RFC 857 *)
| Telnet_suppress_GA (** see RFC 858 *)
| Telnet_status (** see RFC 859 *)
| Telnet_timing_mark (** see RFC 860 *)
| Telnet_ext_opt_list (** see RFC 861 *)
| Telnet_end_of_rec (** see RFC 885 *)
| Telnet_window_size (** see RFC 1073 *)
| Telnet_term_speed (** see RFC 1079 *)
| Telnet_term_type (** see RFC 1091 *)
| Telnet_X_display (** see RFC 1096 *)
| Telnet_linemode (** see RFC 1184 *)
| Telnet_flow_ctrl (** see RFC 1372 *)
| Telnet_auth (** see RFC 1416 *)
| Telnet_new_environ (** see RFC 1572 and 1571 *)
| Telnet_option of int (** all other options *)
(** [telnet_negotiated_option]: names for the most common options, and
* the generic name [Telnet_option] for other options.
*)
type telnet_option_state =
Not_negotiated
| Accepted
| Rejected (** *)
(** An option has one of three states:
* - [Not_negotiated]: There was no negotiation about the option. This means
* that the option is turned off (but this client is allowed to reject
* it explicitly)
* - [Accepted]: Both sides have accepted the option.
* - [Rejected]: One side has rejected the option. This also means that the
* option is off, but the client refuses to send further acknoledgements
* that the option is off (to avoid endless negotiation loops).
*)
val char_of_option : telnet_negotiated_option -> char
(** Converts the option name to the character representing it on the
* octet-stream level.
*)
val option_of_char : char -> telnet_negotiated_option
(** Converts a character representing an option to the internal option
* name.
*)
type telnet_connector =
Telnet_connect of (string * int)
| Telnet_socket of Unix.file_descr (** *)
(** Connectors:
* - [Telnet_connect(host,port)]: The client connects to this port.
* - [Telnet_socket s]: The client uses an already connected socket.
*
* Why [Telnet_socket]? Telnet is a symmetrical protocol; client and servers
* implement the same protocol features (the only difference is the
* environment: a client is typically connected with a real terminal; a server
* is connected with a pseudo terminal). This simply means that this
* implementation of a client can also be used as a server implementation.
* You need only to add code which accepts new connections and which passes
* these connections over to a [telnet_session] object via [Telnet_socket].
*)
(** A telnet session *)
class telnet_session :
object
(** Overwiew
*
* The [telnet_session] object has two queues, one for arriving data,
* one for data to send.
* Once the session object is attached to an event system, it connects
* to the remote peer, and processes the queues. Input is appended to
* the input queue; output found on the output queue is sent to the
* other side.
* If input arrives, a callback function is invoked.
* You may close the output side of the socket by putting [Telnet_eof]
* onto the output queue.
* Once the EOF marker has been received, a [Telnet_eof] is appended to
* the input queue, and the connection is closed (completely). The
* session object detaches from the event system automatically in this
* case.
*
* {b Hints}
*
* Set an input handler as callback function in the session object.
* The input handler is called when new input data have been arrived.
* It should inspect the input queue, process the queue as much as
* possible, and it should remove the processed items from the queue.
* While processing, it may add new items to the output queue.
*
* If you are not within the callback function and add items to the
* output queue, the session object will not detect that there are
* new items to send - unless you invoke the [update] method.
*
* If you want option negotiation, it is the simplest way to use
* the special option negotiation methods. Configure the options
* as you want (invoking [enable], [disable] etc), but do not forget
* to modify the way input is processed. Every [Telnet_will], [_wont],
* [_do], and [_dont] command must be passed to [process_option_command].
*)
method set_connection : telnet_connector -> unit
(** Sets the host name and the port of the remote server to contact. *)
method set_event_system : Unixqueue.event_system -> unit
(** Sets the event system to use. By default, a private event system
* is used.
*)
method set_callback : (bool -> unit) -> unit
(** Sets the callback function. This function is called after new
* commands have been put onto the input queue.
* The argument passed to the callback function indicates whether
* a 'Synch' sequence was received from the remote side or not.
*
* {b Note Synch:} If the client sees a data mark command it will assume
* that it is actually a Synch sequence. The client automatically
* discards any [Telnet_data] commands from the input queue (but not
* [Telnet_data]s inside subnegotiations). The data mark command
* itself remains on the queue.
*)
method set_exception_handler : (exn -> unit) -> unit
(** Sets the exception handler. Every known error condition is
* caught and passed to the exception handler.
* The exception handler can do whatever it wants to do. If it
* raises again an exception, the new exception is always propagated
* up to the caller (whoever this is). Often the caller is the
* event system scheduler (i.e. [Unixqueue.run]); see the documention
* there.
*
* If you do not set the exception handler, a default handler is
* active. It first resets the session (see method [reset]), and
* then wraps the exception into the [Telnet_protocol] exception,
* and raises this exception again.
*)
method output_queue : telnet_command Queue.t
(** The queue of commands to send to the remote side. If you add new
* commands to this queue, do not forget to invoke the [update]
* method which indicates to the event system that new data to
* send is available.
* After commands have been sent, they are removed from the queue.
*)
method input_queue : telnet_command Queue.t
(** The queue of commands received from the remote side. This class
* only adds commands to the queue (and invokes the callback
* function). The user of this class is responsible for removing
* commands from the queue which have been processed.
*)
method get_options : telnet_options
(** Get the configuration options. *)
method set_options : telnet_options -> unit
(** Set the configuration options. *)
method reset : unit -> unit
(** Closes the connection immediately and empties all queues.
* All negotiated options are reset, too.
*)