1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
|
(* $Id: ftp_data_endpoint.mli 143 2005-07-27 20:32:41Z gerd $ *)
(** Senders and receivers for the FTP data connection *)
(* *********************************************************************)
(** {1 Types and Exceptions} *)
(** An [out_record_channel] can be used to output files with record
* structure. This is purely abstract, as Unix does not support such
* files natively, so this kind of channel is usually mapped to a flat
* representation when stored in a real file, e.g. record boundaries
* become newline characters.
*)
class type out_record_channel =
object
inherit Netchannels.out_obj_channel
method output_eor : unit -> unit
(** Finishes the current record.
*
* The record model is as follows: At the beginning of the channel,
* or after [output_eor], a new record can be potentially started.
* However, the record counts only as existing when either at least
* one byte is output, or the record is explicitly ended with a
* [output_eor] call.
*
* This rule allows it to represent channels containing no records.
* There is an ambiguity at the end of the channel, however: It is
* possible that there are characters between the last EOR and the
* EOF. This could also be represented by printing another EOR just
* before EOF. The preferred representation is the latter.
*
* This model correlates to the usual rules for line-structured
* files, so think EOR = EOL.
*)
end
(** An [in_record_channel] can be used to read files with record
* structure. This is purely abstract, as Unix does not support such
* files natively, so this kind of channel is usually mapped to a flat
* representation when stored in a real file, e.g. record boundaries
* become newline characters.
*)
class type in_record_channel =
object
inherit Netchannels.in_obj_channel
method input_eor : unit -> unit
(** Skips over the remaining data of the current record and the
* record boundary to the next record. Raises [End_of_file] when
* the current record is the "EOF" record (see below for explanations).
*
* A record channel can be read as follows: After opening the channel,
* one can read the contents of the first record with the [input]
* method. The end of the record is indicated by an [End_of_file]
* exception. By calling [input_eor], the next record is opened
* and can be read.
*
* After the last real record, there is always a special
* "EOF" record which is empty, and must be ignored by applications
* processing records. This means, after opening an empty channel,
* the current record is this "EOF" record, and [input_eor] raises
* [End_of_file]. After reading a non-empty channel, one can
* do [input_eor] after the last regular record, and the following
* [input_eor] raises [End_of_file].
*)
end
type local_receiver =
[ `File_structure of Netchannels.out_obj_channel
| `Record_structure of out_record_channel
]
(** The [local_receiver] is the object that gets the data received
* over the data connection.
*
* Page structure is not supported.
*)
type local_sender =
[ `File_structure of Netchannels.in_obj_channel
| `Record_structure of in_record_channel
]
(** The [local_sender] is the object that provides the data sent
* over the data connection.
*
* Page structure is not supported.
*)
type transmission_mode =
[ `Stream_mode
| `Block_mode
]
(** The transmission mode as described in RFC 959.
* Compressed mode is not supported.
*)
type descr_state =
[ `Clean
| `Transfer_in_progress
| `Down
]
(** Describes the state of the socket used for data transfers.
* The state [`Clean] means that a new data transfer may be started,
* either because the socket is new, or the last block transfer was
* properly finished. The state [`Transfer_in_progress] means that
* data is being transferred, but also that the transfer is aborted.
* The state [`Down] means that the socket is already at least half-closed,
* i.e. EOF was sent in one direction.
*)
type text_data_repr =
[ `ASCII of Netconversion.encoding
| `ASCII_unix of Netconversion.encoding
| `EBCDIC of Netconversion.encoding
]
(** Possible representation of text data:
* [`ASCII] means an ASCII-compatible encoding where the newline
* character is represented by CR/LF. [`ASCII_unix] is the same
* but newline is only LF. [`EBCDIC] is an EBCDIC variant.
*
* The argument specifies the exact variant to be used, e.g.
* [`ASCII `Enc_iso88591] or [`EBCDIC `Enc_cp1047].
*
* It is illegal to use [`ASCII] or [`ASCII_unix] with an ASCII-
* incompatible encoding, as well as combining [`EBCDIC] with a
* non-EBCDIC encoding. Wrong conversions would be the result of
* this.
*)
(* *********************************************************************)
(** {1 Data Stream Converters} *)
class write_out_record_channel :
repr:text_data_repr ->
Netchannels.out_obj_channel ->
out_record_channel
(** Provides an [out_record_channel] that represents EOR as
* newline character.
*
* @param repr Determines the newline character to use
*)
class read_in_record_channel :
repr:text_data_repr ->
Netchannels.in_obj_channel ->
in_record_channel
(** Provides an [in_record_channel] that takes newline characters as
* EOR representation.
*
* In this implementation, [input_line] can be used to read the full
* contents of a record (=line). However, [input_line] does not
* switch to the next record.
*
* @param repr Determines the newline character to use
*)
class data_converter :
fromrepr:text_data_repr -> torepr:text_data_repr ->
Netchannels.io_obj_channel
(** Creates a data conversion pipe converting [fromrepr] to
* [torepr].
*
* For simplicity, in an [`ASCII] input stream the CR characters are
* discarded, and the LF characters are taken as newline characters.
* In an output [`ASCII] stream, the CR/LF sequence is correctly
* created for newline characters.
*)
(* *********************************************************************)
(** {1 Engines} *)
(** The common type of FTP data engines *)
class type ftp_data_engine =
object
inherit [unit] Uq_engines.engine
method descr : Unix.file_descr
(** The socket to use for data transfers. This class never closes
* this socket, but it may be shut down at least partially.
*)
method descr_state : descr_state
(** The socket state *)
end
(** This engine receives data on a FTP data connection, and forwards
* them to a local receiver. The socket must already be open.
*
* It is ensured that [local_receiver] is always closed after operation
* (whether successful or not). The socket [descr] remains open.
*)
class ftp_data_receiver :
esys:Unixqueue.event_system ->
mode:transmission_mode ->
local_receiver:local_receiver ->
descr:Unix.file_descr ->
unit ->
object
inherit ftp_data_engine
method local_receiver : local_receiver
(** The local receiver. It is closed when the logical EOF is found in the
* data connection
*)
end
(** This engine sends data over a FTP data connection coming from
* a local sender. The socket must already be open.
*
* It is ensured that [local_sender] is always closed after operation
* (whether successful or not). The socket [descr] remains open.
*)
class ftp_data_sender :
esys:Unixqueue.event_system ->
mode:transmission_mode ->
local_sender:local_sender ->
descr:Unix.file_descr ->
unit ->
object
inherit ftp_data_engine
method local_sender : local_sender
(** The local sender. It is closed after usage.
*)
end
|