RFC 2204

ODETTE File Transfer Protocol

๐Ÿ“… published September 1997, from ietf

ODETTE File Transfer Protocol ๐Ÿ“ฌโœจ

Okay bestie, so this is RFC 2204, titled "ODETTE File Transfer Protocol" ๐Ÿ’–. It was written by D. Nash from ODETTE and dated September 1997. Its category is Informational ๐ŸŽ€. The header doesn't mention it obsoleting or updating any other RFC.


Status of This Memo ๐ŸŒธ

okay so this memo is just giving info to the Internet community ๐Ÿซถ. It doesn't specify an Internet standard of any kind, and distribution of it is unlimited ๐Ÿฆ‹.

Abstract โœจ

This one is about a file transfer protocol for swapping electronic data between trading partners ๐Ÿ’….

The protocol is called the ODETTE File Transfer Protocol ๐Ÿ”ฅ. It supports direct communication between installations and indirect communication through a third party clearing centre. ODETTE (the Organisation for Data Exchange by Tele Transmission in Europe) made it for the European motor industry, and it's being shared here so the wider Internet community can use it ๐Ÿš—๐Ÿ’œ.

Network Working Group                                            D. Nash
Request for Comments: 2204                                        ODETTE
Category: Informational                                   September 1997

Table of Contents ๐Ÿ“š

1. Introduction                                               3
      1.1  -  Background                                      3
      1.2  -  Relationship to the original ODETTE Standard    3
      1.3  -  General Principles                              3
      1.4  -  Structure                                       4
      1.5  -  Virtual Files                                   4
      1.6  -  Service Description                             7

2. Network Service (TCP Transport Service)                    7
      2.1  -  Introduction                                    7
      2.2  -  Service Primitives                              7
      2.3  -  Port Assignment                                 9

3. File Transfer Service                                      9
      3.1  -  Model                                          10
      3.2  -  Session Setup                                  11
      3.3  -  File Transfer                                  13
      3.4  -  Session Take Down                              16
      3.5  -  Service State Automata                         19

4. Protocol Specification                                    22
      4.1  -  Overview                                       22
      4.2  -  Start Session Phase                            22
      4.3  -  Start File Phase                               23
      4.4  -  Data Transfer Phase                            26
      4.5  -  End File Phase                                 27
      4.6  -  End Session Phase                              27
      4.7  -  Problem Handling                               28

5. Commands and Formats                                      28
      5.1  -  Conventions                                    28
      5.2  -  Commands                                       29
      5.3  -  Command Formats                                29
      5.4  -  Identification Code                            45

6. ODETTE-FTP Data Exchange Buffer                           46
      6.1  -  Overview                                       46
      6.2  -  Data Exchange Buffer Format                    46
      6.3  -  Buffer Filling Rules                           47

7. Stream Transmission Buffer (TCP only)                     47
      7.1  -  Introduction                                   47
      7.2  -  Stream Transmission Header Format              49

8. Protocol State Machine                                    50
      8.1  -  ODETTE-FTP State Machine                       50
      8.2  -  Error Handling                                 50
      8.3  -  States                                         51
      8.4  -  Input Events                                   53
      8.5  -  Output Events                                  54
      8.6  -  Local Variables                                55
      8.7  -  Local Constants                                55
      8.8  -  Session Connection State Table                 56
      8.9  -  Error and Abort State Table                    58
      8.10 -  Speaker State Table 1                          59
      8.11 -  Speaker State Table 2                          63
      8.12 -  Listener State Table                           65
      8.13 -  Example                                        68

9.  Security Considerations                                  68

Appendix A    Virtual File Mapping Example                   69
Appendix B    ISO 646 Character Subset                       72

Acknowledgements                                             73
References                                                   73
ODETTE Address                                               74
Author's Address                                             74

1. Introduction ๐ŸŒˆ

1.1. Background ๐Ÿ•ฐ๏ธ

So the ODETTE File Transfer Protocol (ODETTE-FTP) was defined back in 1986 by working group four of ODETTE ๐Ÿ’…. They made it to handle the electronic data interchange (EDI) needs of the European automotive industry ๐Ÿš˜. It was built in the spirit of the Open System Interconnection (OSI) model and used the Network Service from the CCITT X25 recommendation ๐Ÿงš.

Over the last ten years it got super widely deployed on everything from personal computers to big mainframes ๐Ÿ’ปโœจ. Then internet tech started spreading everywhere and businesses went global, so ODETTE decided to extend the protocol to use TCP/IP and make it available to the Internet community ๐ŸŒธ๐ŸŒ. Literally iconic glow-up ๐Ÿ‘‘.

This memo describes ODETTE-FTP using the Transmission Control Protocol for its network service ๐Ÿฆ‹.

1.2. Relationship to the original ODETTE Standard ๐Ÿ“–

This memo is an interpretation of version 1.3 of the ODETTE File Transfer Protocol [OFTP]. If there's any ambiguity between this document and the original ODETTE-FTP, the original shall take precedence ๐Ÿซถ.

For ODETTE-FTP on TCP/IP, these sections were added compared to the original document:

  • Section 2 - Network Service
  • Section 7 - Stream Transmission Buffer
  • Appendix A - Virtual File mapping example

1.3. General Principles ๐ŸŽฏ

The whole point of ODETTE-FTP is to move a file between one or more locations in a way that doesn't depend on the data communication network, the system hardware, or the software environment ๐Ÿ’–.

When they designed and specified it, they thought about these factors:

  1. The possible differences of size and sophistication (file storage, small and large systems).
  2. The necessity to work with existing systems (reduce changes to existing products and allow easy implementation).
  3. Systems of different ages.
  4. Systems of different manufactures.
  5. The potential for growth in sophistication (limit impact and avoid changes at other locations).

1.4. Structure ๐Ÿงฉ

ODETTE-FTP is modelled on the OSI reference model ๐Ÿง . It uses the Network Service from level 3 of the model and gives users a File Service, so the protocol spans levels 4 to 7 of the model ๐Ÿ”ฅ.

This memo is closely related to the original 'X.25' specification of the protocol. In the spirit of the OSI model, it describes:

  1. A File Service provided to a user monitor.
  2. A protocol for the exchange of information between peer ODETTE-FTP entities.

Adapting the protocol to TCP was a big deal, and the main goal was to change nothing about the existing protocol ๐Ÿ™ˆ. Implementers should be able to support internet communication with only minor changes to their existing ODETTE-FTP engines. So they added an extra header to the start of each exchange buffer, which lets the TCP byte stream get broken up into the discrete exchange buffers ODETTE-FTP expects ๐Ÿ’…โœจ.

1.5. Virtual Files ๐Ÿ“ฆ

Information is always exchanged between ODETTE-FTP entities in a standard representation called a Virtual File ๐Ÿ’œ. This means data can move around without caring what kind of systems are talking to each other ๐ŸŒˆ.

How a file gets mapped between its local form and its virtual form depends on the system, and this memo doesn't define it ๐Ÿคทโ€โ™€๏ธ.

                              o---------o
                         Site | Local   |
                          A   | File A  |
                              o---------o
                                   |
      o----------------------- Mapping A ------------------------o
      |                            |                             |
      |                       o---------o                        |
      |                       | Virtual |                        |
      |                       |  File   |                        |
      |                       o---------o                        |
      |    o------------------------------------------------o    |
      |    |                                                |    |
      |    |                  ODETTE-FTP                    |    |
      |    |                                                |    |
      |    o------------------------------------------------o    |
      |      o---------o                        o---------o      |
      |      | Virtual |                        | Virtual |      |
      |      |  File   |                        |  File   |      |
      |      o---------o                        o----+----o      |
      |           |                                  |           |
      o------ Mapping B ------------------------ Mapping C ------o
                  |                                  |
             o---------o                        o----+----o
             | Local   | Site              Site | Local   |
             | File B  |  B                 C   | File C  |
             o---------o                        o---------o

A Virtual File is described by a set of attributes that identify and define the data being transferred ๐ŸŽ€. The main attributes are:

1.5.1. Organisation: ๐Ÿ—‚๏ธ

Sequential ๐Ÿงพ

Logical records are presented one after another. The ODETTE-FTP must be aware of the record boundaries ๐Ÿ‘€.

1.5.2. Identification ๐Ÿชช

Dataset Name ๐Ÿท๏ธ

Dataset name of the Virtual File being transfered, assigned by bilateral agreement.

Time stamp (HHMMSS) โฐ

A file qualifier indicating the time the Virtual File was made available for transmission.

Date stamp (YYMMDD) ๐Ÿ“…

A file qualifier indicating the date the Virtual File was made available for transmission.

The Dataset Name, Date and Time attributes are assigned by a Virtual File's Originator and are used to uniquely identify the file. They must not be changed by intermediate locations ๐Ÿ”’.

The Date attribute stores the decade and year in a two digit field. Since ODETTE-FTP only uses this to identify a particular Virtual File, it keeps working correctly in the year 2000 and beyond ๐Ÿฅณ.

The User Monitor may use the Virtual File Date attribute in local processes involving date comparisons and calculations. Any such use is outside the scope of this protocol, and year 2000 handling is a local implementation issue ๐Ÿ’….

1.5.3 Record Format ๐Ÿ’–

Okay bestie, there are four record formats, and they each have their own vibe ๐ŸŽ€

  • Fixed (F): every record in the file is the same length. Very neat, very symmetrical ๐Ÿงš
  • Variable (V): the records can be different lengths. Chaotic but make it work ๐Ÿ’…
  • Unstructured (U): the file is just a stream of data. No structure is defined here, so it's giving free spirit ๐Ÿฆ‹
  • Text File (T): a Text File is a sequence of ASCII characters with no control characters, except CR/LF, which is what separates lines. A line will not have more than 2048 characters ๐Ÿ“

1.5.4 Restart โœจ

ODETTE-FTP can negotiate restarting a Virtual File transmission that got interrupted, which is so iconic ๐Ÿ™Œ Fixed and Variable format files restart on record boundaries. For Unstructured and Text files, the restart position is written as a file offset in 1K (1024 octet) blocks. The restart position is always calculated relative to the Virtual File ๐ŸŒธ

1.6 Service Description ๐Ÿซถ

ODETTE-FTP gives a file transfer service to a user monitor, and then it uses the Internet transport layer stream service to talk to its peers. Ngl, that's a lot of layers, but it's organised ๐Ÿ’œ

These services are described in this memo with service primitives, which fall into four classes:

  • Request (RQ): an entity asks the service to do some work.
  • Indication (IND): a service tells an entity that something happened.
  • Response (RS): an entity answers an event.
  • Confirm (CF): a service tells an entity what the response was.

Services may be confirmed, using the request, indication, response and confirm primitives, or unconfirmed, using just the request and indication primitives ๐Ÿฆ‹

2. Network Service (TCP Transport Service) ๐ŸŒˆ

2.1 Introduction ๐ŸŒธ

ODETTE-FTP peers talk to each other through either the OSI Network Service or the Transmission Control Protocol Transport Service [TCP]. Both are described with service primitives for request, indication, response and confirmation actions ๐Ÿ’–

For the internet environment, the Network Service primitives below need to be mapped to the matching Transport Service primitives. This section covers the network service primitives ODETTE-FTP uses and how they line up with the TCP interface. In practice, the local transport service application programming interface is what gets used to reach the TCP service โœจ

2.2 Service Primitives ๐Ÿ’…

All Network primitives can be mapped directly to the matching Transport primitives when using TCP. Slay, simple ๐Ÿ˜ญ

2.2.1 Network Connection ๐ŸŽ€

   N_CON_RQ   ------>   N_CON_IND
   N_CON_CF   <------   N_CON_RS

This is how a connection gets set up. The requesting ODETTE-FTP peer uses the N_CON_RQ primitive to ask for an active OPEN of a connection to a peer ODETTE-FTP, which is the Responder. The Responder has already asked for a passive OPEN. The Responder is told about the incoming connection through N_CON_IND, and it accepts with N_CON_RS. The requester finds out its OPEN request has completed when _CON_CF comes in ๐Ÿงš

Parameters

   Request           Indication        Response          Confirmation
   ---------------------------------------------------------------------
   Dest addr ------> same              same              same

2.2.2 Network Data ๐Ÿฆ‹

      N_DATA_RQ  ------>   N_DATA_IND

Data exchange is an unconfirmed service. The Requester hands data over for transmission to the network service with the N_DATA_RQ primitive. The Responder is told that data is available through N_DATA_IND. In practice, the notification and the receipt of data can be combined, for example when a blocking read from the network socket returns ๐ŸŒŠ

Parameters

   Request                  Indication
   ---------------------------------------------------------------------
   Data ------------------> same

2.2.3 Network Disconnection ๐Ÿ“

      N_DISC_RQ  ------>   N_DISC_IND

An ODETTE-FTP requests the end of a connection with the N_DISC_RQ service primitive. Its peer gets notified of the CLOSE through an N_DISC_IND event. It's recognised that each peer must issue an N_DISC_RQ primitive to complete the TCP symmetric close procedure. So it's a two-way thing, no cap ๐Ÿ™ˆ

2.2.4 Network Reset ๐Ÿ’€

    ------>   N_RST_IND

An ODETTE-FTP entity is told about a network error through an N_RST_IND event. Worth noting that N_RST_IND would also be generated if a peer RESETS the connection. That's ignored here, though, because ODETTE-FTP never sends N_RST_RQ to the Network Service ๐Ÿ‘‘

2.3 Port Assignment ๐ŸŽ€

An ODETTE-FTP requester picks a suitable local port of its own ๐Ÿ’–

The responding ODETTE-FTP listens for connections on Registered Port 3305, and the service name is 'odette-ftp' โœจ

3. File Transfer Service ๐ŸŒธ

The File Transfer Service describes what an ODETTE-FTP Entity offers to its User Monitor. How the service primitives are implemented is a local matter, so it's up to each implementation ๐Ÿงš

3.1 Model ๐Ÿฆ‹

          o-------------------o             o-------------------o
          |                   |             |                   |
          |   USER  MONITOR   |             |   USER  MONITOR   |
          |                   |             |                   |
          o-------------------o             o-------------------o
                  |   A                             |   A
   ...............|...|... FILE TRANSFER SERVICE ...|...|...............
                  |   |                             |   |
      F_XXX_RQ/RS |   | F_XXX_IND/CF    F_XXX_RQ/RS |   | F_XXX_IND/CF
                  V   |                             V   |
          o-------------------o             o-------------------o
          |                   |- - - - - - >|                   |
          | ODETTE-FTP Entity |   E-Buffer  | ODETTE-FTP Entity |
          |                   |< - - - - - -|                   |
          o-------------------o             o-------------------o
                  |   A                             |   A
      N_XXX_RQ/RS |   | N_XXX_IND/CF    N_XXX_RQ/RS |   | N_XXX_IND/CF
                  |   |                             |   |
   ...............|...|...... NETWORK SERVICE ......|...|...............
                  V   |                             V   |
        o---------------------------------------------------------o
        |                                                         |
        |                      N E T W O R K                      |
        |                                                         |
        o---------------------------------------------------------o

         Key:  E-Buffer - Exchange Buffer
               F_       - File Transfer Service Primitive
               N_       - Network Service Primitive

3.2 Session Setup ๐Ÿ’œ

3.2.1 Session Connection Service ๐ŸŽ€

                             |            |
           F_CONNECT_RQ ---->|------------|----> F_CONNECT_IND
                             |            |
           F_CONNECT_CF <----|------------|<---- F_CONNECT_RS
                             |            |

Parameters

   Request           Indication        Response          Confirm
   ---------------------------------------------------------------------
   called-address -> same              ---               ----
   calling-address-> same              ---               ----
   ID1 ------------> same              ID2 ------------> same
   PSW1------------> same              PSW2 -----------> same
   mode1 ----------> mode2 ----------> mode3 ----------> same
   restart1 -------> same -----------> restart2 -------> same
   ---------------------------------------------------------------------

Mode

This tells you the file transfer capabilities of the entity sending or receiving an F_CONNECT primitive, and it holds for the whole session ๐ŸŒˆ

Value:

  • Sender-Only: the entity can only send files.
  • Receiver-Only: the entity can only receive files.
  • Both: the entity can both send and receive files.

Negotiation:

  • Sender-Only: not negotiable.
  • Receiver-Only: not negotiable.
  • Both: can be negotiated down to Sender-Only or Receiver-Only, by the User Monitor or the ODETTE-FTP entity ๐Ÿ”ฅ
   Request           Indication        Response          Confirm
   ---------------------------------------------------------------------
   Sender-only ----> Receiver-only --> Receiver-only --> Sender-only

   Receiver-only --> Sender-only ----> Sender-only ----> Receiver-only

   Both -----+-----> Both ----+------> Both -----------> Both
             |             or +------> Receiver-only --> Sender-only
             |             or +------> Sender-only ----> Receiver-only
             |
          or +-----> Receiver-only --> Receiver-only --> Sender-only
          or +-----> Sender-only ----> Sender-only ----> Receiver-only
   ---------------------------------------------------------------------

Restart

This tells you the file transfer restart capabilities of the User Monitor โœจ

Value:

Negotiation:

   Request           Indication        Response          Confirm
   ---------------------------------------------------------------------
   restart = Y ----> restart = Y --+-> restart = Y ----> restart = Y
                                or +-> restart = N ----> restart = N

   restart = N ----> restart = N ----> restart = N ----> restart = N
   ---------------------------------------------------------------------

3.3 File Transfer ๐ŸŒท

3.3.1 File Opening ๐Ÿฆ‹

                             |            |
        F_START_FILE_RQ ---->|------------|----> F_START_FILE_IND
                             |            |
   F_START_FILE_CF(+|-) <----|------------|<---- F_START_FILE_RS(+|-)
                             |            |

Parameters:

   Request         Ind.   RS(+)          CF(+)     RS(-)         CF(-)
   --------------------------------------------------------------------
   file-name ----> same   ----           ----      ----          ----
   date-time ----> same   ----           ----      ----          ----
   destination---> same   ----           ----      ----          ----
   originator----> same   ----           ----      ----          ----
   rec-format----> same   ----           ----      ----          ----
   rec-size -----> same   ----           ----      ----          ----
   file-size-----> same   ----           ----      ----          ----
   restart-pos1--> same-> restart-pos2-> same      ----          ----
   ----            ----   ----           ----      cause ------> same
   ----            ----   ----           ----      retry-later-> same
   --------------------------------------------------------------------

Notes:

  1. Retry-later has the values "Y" or "N".
  2. Cause is the reason for refusing the transfer (1,..,13,99).
  3. Restart-pos1 not equal to 0 is only valid if restart has been agreed during initial negotiation.
  4. Restart-pos2 is less than or equal to restart-pos1 ๐Ÿ“

3.3.2 Data Regime ๐Ÿ’œ

                             |            |
              F_DATA_RQ ---->|------------|----> F_DATA_IND
                             |            |

Notes:

  1. The data format within a F_DATA primitive is locally defined.
  2. The File Transfer service may have to provide a flow control mechanism to regulate the flow of F_DATA primitives. This is the bit where traffic control matters, so keep an eye on it ๐Ÿซถ

3.3.3 File Closing ๐ŸŽ€

Okay bestie, time to wrap up a file! ๐Ÿ’… Here's how the close works, with the request and indication on the left and the confirm and response on the right:

                             |            |
         F_CLOSE_FILE_RQ --->|------------|----> F_CLOSE_FILE_IND
                             |            |
    F_CLOSE_FILE_CF(+|-) <---|------------|<---- F_CLOSE_FILE_RS(+|-)
                             |            |

Here's the parameter table, which is the part that makes it click for me ๐Ÿฆ‹

   Parameters

   Request         Ind    RS(+)          CF(+)     RS(-)         CF(-)
   ---------------------------------------------------------------------
   rec-count --->  same   ----           ----      ----          ----
   unit-count -->  same   ----           ----      ----          ----
   ----            ----   Speaker=Y ---> Speaker=N ----          ----
   ----            ----   Speaker=N ---> Speaker=Y ----          ----
   ----            ----   ----           ----      cause --->    same
   ---------------------------------------------------------------------

So in a positive Close File response (F_CLOSE_FILE_RS(+)), the current Speaker gets two choices ๐Ÿ‘‘:

  1. Set Speaker to "Yes" and become the Speaker.
  2. Set Speaker to "No" and remain the Listener.

The File Transfer service makes sure the speaker setting matches what the peer user is actually capable of. Smart, right? ๐Ÿงš

The turn is never exchanged when the response or confirmation is negative. No turn swap on a failure, periodt ๐Ÿ™…โ€โ™€๏ธ

Last but not least: only the Speaker is allowed to send F_XXX_FILE_RQ primitives. Listeners just have to sit there and be cute ๐ŸŒธ

3.3.4 Exchanging the Turn ๐Ÿ”„

3.3.4.1 Initial Turn (First Speaker)

The Initiator becomes the first Speaker at the end of the Session Setup, which is when it has received F_CONNECT_CF and the Responder has sent F_CONNECT_RS. The very first Speaker is locked in, no drama โœจ

3.3.4.2 Following Turns

Here are the rules for passing the mic around ๐ŸŽค

  1. At each unsuccessful End of File, the turn is not exchanged.
  2. At each successful End of File, the turn is exchanged if the Listener asks for it:
    • The current Listener receives F_CLOSE_FILE_IND (Speaker = choice).
    • If the Listener answers F_CLOSE_FILE_RS(Speaker = YES), it becomes Speaker. The old Speaker receives F_CLOSE_FILE_CF (Speaker = NO) and becomes Listener. ๐Ÿฆ‹
    • If the Listener answers F_CLOSE_FILE_RS(Speaker = NO), it remains Listener. The Speaker receives F_CLOSE_FILE_CF (Speaker = YES) and stays Speaker.
  3. The Speaker can send a Change Direction request (F_CD_RQ) to become the Listener. The Listener receives a Change Direction indication (F_CD_IND) and becomes the Speaker.
  4. To stop F_CD_RQ/IND from looping forever, it is an error to send F_CD_RQ right after receiving an F_CD_IND. Don't be that person ๐Ÿ™ˆ

3.3.5 End to End Response ๐Ÿ’Œ

This service is started by the current Speaker, but only if no file transfer is in progress. Its job is to send an End-to-End response from the final destination back to whoever originated the file.

                             |            |
              F_EERP_RQ ---->|------------|----> F_EERP_IND
                             |            |
   Parameters

   Request           Indication
   ------------------------------------
   filename -------> same
   date -----------> same
   time -----------> same
   destination ----> same
   originator -----> same
   ------------------------------------

Here's how it plays with the turn ๐ŸŽ€

  • Only the Speaker may send an End to End Response request.
  • Invoking the EERP service does not change the turn.
  • If an F_CD_IND was just received before F_EERP_RQ is issued, that gets you out of the special condition the F_CD_IND created. Before this, you could issue F_RELEASE_RQ but not F_CD_RQ right after getting F_CD_IND. Once you've sent F_EERP_RQ, you're back to normal Speaker status, where F_CD_RQ is valid but F_RELEASE_RQ isn't. ๐Ÿ’…

3.4 Session Take Down ๐ŸŒ™

3.4.1 Normal Close ๐Ÿ’ค

                             |            |
           F_RELEASE_RQ ---->|------------|----> F_RELEASE_IND
                             |            |
   Parameters

   Request                  Indication
   ---------------------------------------------------------------------
   reason = normal -------> ----
   ---------------------------------------------------------------------

Only the Speaker can start a Release. The Speaker can only send a Release request (F_RELEASE_RQ) right after receiving an unsolicited Change Direction indication (F_CD_IND). That's how the other partner gets the message that no more files are coming in this session ๐Ÿ“ญ

Peer ODETTE-FTP entities do a normal session release by putting Reason = Normal into an End Session (ESID) command.

3.4.2 Abnormal close โš ๏ธ

                             |            |
           F_RELEASE_RQ ---->|------------|----> F_ABORT_IND
                             |            |
   Parameters

   Request                  Indication
   ---------------------------------------------------------------------
   reason = error value --> same (or equivalent)
                              AO (Abort Origin) = (L)ocal or (D)istant
   ---------------------------------------------------------------------

An abnormal session release can be started by either the Speaker or the Listener, and by either the user or the provider. It can happen at any point in the session ๐Ÿ˜ฌ

Peer ODETTE-FTP entities do an abnormal session release by putting Reason = Error-value into an End Session (ESID) command.

The abnormal release covers these types of error:

  1. The service provider starts an abnormal release in these cases:
    1. Protocol error
    2. Failure of the Start Session (SSID) negotiation
    3. Command not recognised
    4. Exchange buffer size error
    5. Resources not available
    6. Other unspecified abort code (with "REASON" = unspecified)
  2. The User Monitor starts an abnormal release in these cases:
    1. Local site emergency close down
    2. Resources not available
    3. Other unspecified abort code (with "REASON" = unspecified)

Other error types may be handled by aborting the connection. ๐Ÿšจ

3.4.3 Abort ๐Ÿ›‘

                             |            |
             F_ABORT_RQ ---->|------------|----> F_ABORT_IND
                             |            |
             User Initiated Abort
                             |            |
            F_ABORT_IND <----|------------|----> F_ABORT_IND
                             |            |
            Provider Initiated Abort
   Parameters

   Request                  Indication
   ---------------------------------------------------------------------
   --                       R  (Reason): specified or unspecified
   --                       AO (Abort Origin): (L)ocal or (D)istant
   ---------------------------------------------------------------------

Either entity can invoke Abort at any time. The service provider can also start an abort if it detects an error ๐Ÿšซ

3.4.4 Explanation of Session Take Down Services ๐Ÿ“–

            User  | OFTP |        Network       | OFTP |  User
   ---------------|------|----------------------|------|---------------
                  |      |                      |      |

   1. Normal Release

     F_RELEASE_RQ |      | ESID(R=normal)       |      | F_RELEASE_IND
   *--------------|->  ==|======================|=>  --|-------------->
     (R=normal)   |      |                      |      |


   2. User Initiated Abnormal Release

     F_RELEASE_RQ |      | ESID(R=error)        |      | F_ABORT_IND
   *--------------|->  ==|======================|=>   -|-------------->
   (R=error value)|      |                      |      | (R=error,AO=D)


            User  | OFTP |        Network       | OFTP |  User
   ---------------|------|----------------------|------|---------------
                  |      |                      |      |

   3. Provider Initiated Abnormal Release

     F_ABORT_IND  |      | ESID(R=error)        |      | F_ABORT_IND
   <--------------|-*  *=|======================|=>  --|-------------->
                  |      |                      |      |


   4. User Initiated Connection Abort

    F_ABORT_RQ    |      | N_DISC_RQ            |      | F_ABORT_IND
   *--------------|->  --|--------->..----------|->  --|-------------->
                  |      |           N_DISC_IND |      | (R=unsp.,AO=D)


   5. Provider Initiated Connection Abort

     F_ABORT_IND  |      | N_DISC_RQ            |      | F_ABORT_IND
   <--------------|-*  *-|--------->..----------|->  --|-------------->
   (R=error,AO=L) |      |           N_DISC_IND |      | (R=unsp.,AO=D)

           Key:  *        Origin of command flow
                 F_ --->  File Transfer Service primitive
                 N_ --->  Network Service primitive
                    ===>  ODETTE-FTP (OFTP) protocol message

3.5 Service State Automata ๐Ÿค–

This state automaton describes the service the way the User Monitor sees it. Events that cause a state transition are in lower case, and the resulting action is in upper case where it makes sense.

3.5.1 Idle State Diagram ๐ŸŒˆ

                                 o------------o
                     decision    |            |  f_connect_ind
               +-----------------|    IDLE    |-----------------+
               |   F_CONNECT_RQ  |    (0)     |  F_CONNECT_RS   |
               |                 o------------o                 |
               V                                                |
      o-----------------o                                       |
      |                 |                                       |
      | I_WF_FCONNECTCF |                                       |
      |                 |                                       |
      o--------+--------o                                       |
               |                                                |
               | F_CONNECT_CF                                   |
               V                                                V
      o-----------------o                              o-----------------o
      |                 |                              |                 |
      |  IDLE  SPEAKER  |                              | IDLE  LISTENER  |
      |       (1)       |                              |       (2)       |
      |   See Speaker   |                              |  See Listener   |
      |  State Diagram  |                              |  State Diagram  |
      |                 |                              |                 |
      o-----------------o                              o-----------------o

3.5.2 Speaker State Diagram โœจ

okay so this one is the speaker's side of the state machine, and it's giving main character energy ๐Ÿ’… the IDLE SPEAKER state is where all the drama starts ๐ŸŽ€

   o-----------------o                              o-----------------o
   |  IDLE LISTENER  |                              |      IDLE       |
   | CD_RQ just sent |                              |     see (0)     |
   | see (3), Listen |                              |      Idle       |
   |  State Diagram  |                              |  State Diagram  |
   o-----------------o                              o-----------------o
            A                                                A
            |                                                |
        decision          decision                        decision
        F_CD_RQ    +----------------+                   F_RELEASE_RQ
            |      |     F_EERP_RQ  |                        |
   o=================o              |               o-----------------o
   |                 |<-------------+               |  IDLE SPEAKER   |
   |  IDLE SPEAKER   |                              |       (4)       |
   |       (1)       |       decision               |     CD_IND      |
   |                 |<-----------------------------|  just received  |
   o=================o       F_EERP_RQ              o-----------------o
     A  A        |                                               |
     |  |        | decision and P1              decision and P1  |
     |  |        +-----------------+       +---------------------+
     |  |         F_START_FILE_RQ  |       |    F_START_FILE_RQ
     |  |                          V       V
     |  |                      o---------------o
     |  |  f_file_start_cf(-)  |               |
     |  +----------------------|    OPENING    |
     |                         |               |
     |                         o---------------o
     |                                 |
   f_file_close_cf(-)          f_start_file_cf(+)
     and not P2                        |
     |                                 V
   o---------------o           o---------------o
   |               |           |               |------------------+
   |    CLOSING    |           | DATA TRANSFER |  record to send  |
   |               |           |               |<-----------------+
   o---------------o           o---------------o    F_DATA_RQ
     |         A                   |
     |         |    end of file    |
     |         +-------------------+
     |            F_CLOSE_FILE_RQ
     |                                              o-----------------o
     |                f_close_file(+) and P2        |  IDLE LISTENER  |
     +--------------------------------------------->| see (2), Listen |
                                                    |  State Diagram  |
   Predicates:                                      o-----------------o
   P1: Mode = Both or (Mode = Sender-Only)
   P2: Negative confirmation or (positive confirmation, Speaker = YES)

3.5.3 Listener State Diagram ๐ŸŽง

and now the listener's side, which is basically the speaker's mirror image ๐Ÿชž the vibes are very "I heard you, I'm answering" ๐Ÿซถ

   o-----------------o                              o-----------------o
   |  IDLE SPEAKER   |                              |      IDLE       |
   |   CD_IND just   |                              |                 |
   | received see(4) |                              |     see (0)     |
   |  Speaker State  |                              |      Idle       |
   |     Diagram     |                              |  State Diagram  |
   o-----------------o                              o-----------------o
            A                                                A
            |                                                |
         decision     f_eerp_ind                          decision
         F_CD_IND  +--------------+                    F_RELEASE_IND
            |      |              |                          |
   o=================o            |                 o-----------------o
   |                 |<-----------+    f_eerp_ind   |                 |
   |                 |<-----------------------------|  IDLE LISTENER  |
   |  IDLE LISTENER  |                              |       (3)       |
   |                 | f_start_file_ind             |      CD_RQ      |
   |       (2)       |    and not p2               |    just sent    |
   |                 |---------------------+        |                 |
   o=================o F_START_FILE_RS(-)  |        o-----------------o
     A   |      A  A                       |           |          |
     |   |      |  +-----------------------+           |          |
     |   |      |                                      |          |
     |   |      | f_start_file_ind and not p2          |          |
     |   |      +--------------------------------------+          |
     |   |               F_START_FILE_RS(-)                       |
     |   |                                                        |
     |   |           f_start_file_ind           f_start_file_ind  |
     |   |              and p2                        and p2      |
     |   +-------------------------------+     +------------------+
     |               F_START_FILE_RS(+)  |     | F_START_FILE_RS(+)
     |                                   V     V
     |                              o---------------o
     |  f_close_file_ind and not p1 |     DATA      |-------------+
     +------------------------------|   TRANSFER    |             |
          F_CLOSE_FILE_RS(-)        |               |<------------+
                                    o---------------o  F_DATA_IND
   o---------------o                           |
   | IDLE SPEAKER  |  f_close_file_ind and p1  |
   | see (1), Spkr |<--------------------------+
   | State Diagram |    F_CLOSE_FILE_RS(+)
   o---------------o

   Predicates:
   P1: (decision to send F_CLOSE_FILE_RS(+)) and
       (decision to set Speaker = yes in F_CLOSE_FILE_RS(+))
   P2: (decision to send F_START_FILE_RS(+))

4. Protocol Specification โœจ

4.1 Overview ๐ŸŒธ

okay so ODETTE-FTP is split into five operating phases, and they go in this order ๐Ÿ‘‘

   Start Session
   Start File
   Data Transfer
   End File
   End Session

after End File, an ODETTE-FTP entity may start a brand new Start File phase, or it can end the whole session in the End Session phase ๐Ÿฆ‹

peers chat by sending and receiving messages inside Exchange Buffers over the Network Service ๐Ÿ’Œ every Exchange Buffer carries exactly one of these commands ๐Ÿ’…

   SSRM    Start Session Ready Message
   SSID    Start Session
   SFID    Start File
   SFPA    Start File Positive Answer
   SFNA    Start File Negative Answer
   DATA    Data
   CDT     Set Credit
   EFID    End File
   EFPA    End File Positive Answer
   EFNA    End File Negative Answer
   ESID    End Session
   CD      Change Direction
   EERP    End to End Response
   RTR     Ready To Receive

the rest of this section walks through the protocol flows, and Section five has the full command formats ๐Ÿงš

4.2 Start Session Phase ๐ŸŽ€

the Start Session phase kicks off right after the network connection is established ๐Ÿ“

4.2.1 Entity Definition

the ODETTE-FTP entity that started the network connection becomes the Initiator ๐Ÿซถ its peer becomes the Responder ๐Ÿ’œ

4.2.2 Protocol Sequence

the first message must be sent by the Responder ๐Ÿ‘‘ here's how the handshake goes โœจ

   1. Initiator <-------------SSRM -- Responder   Ready Message
                -- SSID ------------>             Identification
                <------------ SSID --             Identification

4.3 Start File Phase ๐Ÿ“

4.3.1 Entity Definition

the Initiator from the Start Session phase becomes the Speaker, and the Responder becomes the Listener ๐ŸŽค the roles can flip when the Speaker sends a Change Direction command to the Listener ๐Ÿ”„

4.3.2 Protocol Sequence

here are the sequences, and yes, one of them loops back to step 1 ๐Ÿ”

   1. Speaker  -- SFID ------------> Listener   Start File
               <------------ SFPA --            Answer YES


   2. Speaker  -- SFID ------------> Listener   Start File
               <------------ SFNA --            Answer NO
                     Go To 1

   2. Speaker  -- CD --------------> Listener   Change Direction
      Listener <------------ EERP -- Speaker    End to End Response
               -- RTR ------------->            Ready to Receive
               <------------ SFID --            Start File
Note: The User Monitor should take steps to prevent a loop situation occurring. ๐Ÿ™ˆ

4.3.3 Restart Facilities ๐Ÿ”

the Start File command has a count in it, so an interrupted transfer can be restarted by negotiating from that point ๐Ÿ’– if restart isn't available, the restart count must be set to zero ๐Ÿ’€ the sender then starts with the lowest record count + 1 โœจ

4.3.4 Broadcast Facilities ๐Ÿ“ก

the destination in a Start File command can be set in one of two ways ๐ŸŒˆ

  1. An explicitly defined destination.
  2. A group destination that allows an intermediate location to broadcast the Virtual File to multiple destinations.

if the destination isn't known, the Listener will send a negative answer to the Speaker ๐Ÿฅบ

4.3.5 Priority ๐Ÿ†

how files get prioritised for transmission is left up to the local implementation, so each host decides for itself ๐Ÿง  for a bit of flexibility, there's a change direction mechanism in the End File phase ๐Ÿฆ‹

4.3.6 End To End Response (EERP) ๐Ÿ’Œ

Okay bestie, the End to End Response (EERP) command is how the originator of a Virtual File finds out it was successfully delivered to its final destination โœจ. Once it knows that, it can do little housekeeping tasks, like deleting its copies of the delivered data ๐Ÿงน๐Ÿ’….

A Response Command MUST be sent from the location doing the final processing or distribution of the data back to the originator. The Response is mandatory and MAY be sent in the same session or in any later one ๐Ÿซถ.

When an intermediate location broadcasts or distributes a Virtual File, it MUST receive a Response command from every location it forwarded the data to before it sends its own Response ๐Ÿ”ฅ. That way the Response the originator gets accounts for all the destination locations, no one left out ๐Ÿ˜ญ. So an intermediate location has to keep track of the status of the files it processes over time ๐Ÿ—‚๏ธ.

Example: Point to Point

Location A sends file Ba to Location B, which sends an EERP back to location A after it successfully receives the file ๐Ÿฆ‹.

o----------o                          o-----------o
| Loc. A   |----------- S1 ---------->| Loc. B    |
|          |                          |           |
| [Ba]     |<---------- R2 -----------| [Ba]      |
+----------o                          o-----------o

Key: S - File Transfer R - Response EERP [Ba] - File for B from A

Example: Data distribution

Location A sends a Virtual File with data for distribution to locations B and C, going through clearing centres E1 and E2 ๐ŸŒธ. Clearing centre E1 has to wait for a response from E2 (for file Ba) and from location C before it sends its response, R8, to location A ๐Ÿ’œ. Clearing centre E2 can only send response R7 to E1 once location B acknowledges file Ba with response R6 โœจ.

o---------o        o---------o        o---------o        o---------o
| Loc. A  |-- S1 ->| Loc. E1 |-- S2 ->| Loc. E2 |-- S5 ->| Loc. B  |
|         |        |         |        |         |        |         |
| [Ba,Ca] |<- R8 --| [Ba,Ca] |<- R7 --| [Ba]    |<- R6 --| [Ba]    |
o---------o        o---------o        o---------o        o---------o
                      A   |
                      |   |           o---------o
                      |   +----- S3 ->| Loc. C  |
                      |               |         |
                      +--------- R4 --| [Ca]    |
                                      o---------o

Example: Data collection

Locations A and B send files Ca and Cb to clearing centre E1, which forwards both files to location C in one single Virtual File ๐ŸŽ€. When E1 gets response R4 from C, it sends response R5 to location A and R6 to location B ๐Ÿ“.

o---------o        o---------o        o---------o
| Loc. A  |-- S1 ->| Loc. E1 |-- S3 ->| Loc. C  |
|         |        |         |        |         |
| [Ca]    |<- R5 --| [Ca,Cb] |<- R4 --| [Ca,Cb] |
o---------o        o---------o        o---------o
                      A   |
o---------o           |   |
| Loc. B  |-- S2 -----+   |
|         |               |
| [Cb]    |<- R6 ---------+
o---------o

4.3.7 Ready To Receive Command (RTR) ๐Ÿงš

So an EERP doesn't flood the link and jam up two neighbouring nodes ๐Ÿšง, we have the Ready To Receive (RTR) command ๐Ÿ’–. The RTR acts like an EERP acknowledgement for flow control, but it has no end-to-end meaning ๐Ÿ™ˆ.

   Speaker  -- EERP ------------> Listener   End to End Response
            <------------- RTR --            Ready to Receive
            -- EERP ------------>            End to End Response
            <------------- RTR --            Ready to Receive
            -- SFID ------------>            Start File
                      or
            -- CD -------------->            Exchange the turn

After sending an EERP, the Speaker MUST wait for an RTR before sending any other commands โณ.


4.4 Data Transfer Phase ๐ŸŒŠ

Virtual File data flows from the Speaker to the Listener during the Data Transfer phase, which starts once the Start File phase is done ๐Ÿ’œ.

4.4.1 Protocol Sequence ๐ŸŽ€

To stop congestion at the protocol level, there's a flow control mechanism called the Credit (CDT) command ๐Ÿ›ก๏ธ.

A Credit limit gets negotiated in the Start Session phase. It represents how many Data Exchange Buffers the Speaker is allowed to send before it has to wait for a Credit command from the Listener ๐Ÿงฎ.

The available credit starts out set to the negotiated value by the Start File positive answer, which works as an implicit Credit command โœจ. The Speaker takes one off the available credit count for every data buffer it sends to the Listener ๐Ÿ“‰.

When the available credit runs out, the Speaker MUST wait for a Credit command from the Listener, or else a protocol error will happen and the session gets aborted ๐Ÿšจ.

The Listener SHOULD try its best to send the Credit command without delay, so the Speaker doesn't get stuck blocking ๐Ÿ™.

1. Speaker  -- SFID ------------> Listener   Start File
            <------------ SFPA --            Answer YES

2. If the Credit Value is set to 2

   Speaker  -- Data ------------> Listener   Start File
            -- Data ------------>
            <------------- CDT --            Set Credit
            -- Data ------------>
            -- EFID ------------>            End File

4.5 End File Phase ๐Ÿ

4.5.1 Protocol Sequence ๐Ÿ’…

The Speaker tells the Listener it's done sending a Virtual File by sending an End File (EFID) command ๐Ÿ“ฉ. The Listener replies with a positive or negative End File command, and it has the option to ask for a Change Direction command from the Speaker ๐Ÿ”„.

1. Speaker  -- EFID ------------> Listener   End File
            <------------ EFPA --            Answer YES


2. Speaker  -- EFID ------------> Listener   End File
            <------------ EFPA --            Answer YES + CD
            -- CD -------------->            Change Direction
   Listener <------------ EERP -- Speaker    End to End Response
            -------------- RTR ->            Ready to Receive
            Go to Start File Phase


3. Speaker  -- EFID ------------> Listener   End File
            <------------ EFNA --            Answer NO

4.6 End Session Phase ๐Ÿ‘‹

4.6.1 Protocol Sequence ๐ŸŒˆ

The Speaker ends the session by sending an End Session (ESID) command ๐Ÿซถ.

1. Speaker  -- EFID ------------> Listener   End File
            <------------ EFPA --            Answer YES
            -- CD -------------->            Change Direction
   Listener <------------ ESID -- Speaker    End Session

4.7 Problem Handling ๐Ÿ› ๏ธ

Error detection and handling SHOULD be done as close to the problem as possible ๐Ÿ”. That makes it way easier to figure out what went wrong and fix it ๐Ÿ’ก. Each layer of the reference model is responsible for its own error handling ๐Ÿงฑ.

ODETTE-FTP can spot protocol errors through how its state machine is built, and it uses activity timers to catch session hang conditions โฑ๏ธ. These mechanisms are separate from the End to End controls ๐Ÿ™…โ€โ™€๏ธ.

4.7.1 Protocol Errors ๐Ÿ’€

If a protocol error happens, the session gets terminated and application activity is aborted. Both locations go back to the IDLE state ๐Ÿ˜ต.

4.7.2 Timers โฐ

To protect against application and network hang conditions, ODETTE-FTP uses activity timers for every situation where a response is required โณ. The timers, and what to do when they expire, are described in section 8, the Protocol State Machine ๐Ÿ“–.

4.7.3 Clearing Centres ๐Ÿฌ

Using clearing centres opens the door to errors from the data processing that happens inside the centre ๐Ÿ™ƒ. Those errors aren't directly related to ODETTE-FTP or the communication network, so they're outside the scope of this specification ๐Ÿšซ.


5. Commands and Formats ๐Ÿ“ฆ

ODETTE-FTP entities talk to each other through Exchange Buffers ๐Ÿ’ฌ. The Command Exchange Buffers are described below โฌ‡๏ธ. Virtual File data gets carried in Data Exchange Buffers, which are described in Section 6 ๐Ÿง.

5.1 Conventions ๐Ÿ“

5.1.1 Representation unit:

The basic unit of information is an octet, which is eight bits ๐Ÿ”ข.

5.1.2 Values and Characters:

The ISO 646 IRV 7-bit coded character set [ISO-646] is used to encode constants and strings inside command exchange buffers ๐Ÿ”ค.

5.2 Commands ๐ŸŽฏ

A Command Exchange Buffer holds a single command, starting right at the beginning of the buffer. Commands and data are never mixed inside one Exchange Buffer ๐Ÿ™…โ€โ™€๏ธ. Each command has a fixed length and can not be compressed ๐Ÿ“.

Components:

  1. Command identifier:

The first octet of an Exchange Buffer is the Command Identifier, and it defines the format of the buffer ๐Ÿชช.

  1. Parameter(s):

Command parameters are stored in fixed fields inside a Command Exchange Buffer. All values are REQUIRED ๐Ÿ’–.

5.3 Command Formats ๐Ÿงพ

The ODETTE-FTP commands are described below, using the following definitions ๐Ÿ“š.

  • Position (Pos.): the field offset within the command exchange buffer, counted from a zero origin ๐Ÿ“.
  • Field: the name of the field ๐Ÿท๏ธ.
  • Description: a description of the field ๐Ÿ“.
  • Format:
    • F - A field containing fixed values. All allowable values for the field are listed in the command definition.
    • V - A field with variable values within a defined range. For example, the SFIDFSIZ field may contain any integer value between 0000000 and 9999999.
    • X(n) - An alphanumeric field of length n octets.
    • 9(n) - A numeric field of length n octets.

All attributes are in character format ๐Ÿ”ก.

A String contains alphanumeric characters from the following set ๐Ÿ” :

The numerals:               0 to 9
The upper case letters:     A to Z
The following special set:  / - . & ( ) space.

Space is not allowed as an embedded character ๐Ÿšซ. Numeric fields are always right justified, and left padding with zeros MUST be done when needed ๐Ÿช„.

5.3.1 SSRM - Start Session Ready Message ๐Ÿš€

o-------------------------------------------------------------------o
|       SSRM        Start Session Ready Message                     |
|                                                                   |
|       Start Session Phase     Initiator <---- Responder           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | SSRMCMD   | SSRM Command, 'I'                     | F X(1)  |
|   1 | SSRMMSG   | Ready Message, 'ODETTE FTP READY '    | F X(17) |
|  18 | SSRMCR    | Carriage Return                       | F X(1)  |
o-------------------------------------------------------------------o

SSRMCMD ๐Ÿ†” Command Code, character. Value: 'I', the SSRM Command identifier.

SSRMMSG ๐Ÿ’ฌ Ready Message, String(17). Value: 'ODETTE FTP READY '.

SSRMCR โ†ฉ๏ธ Carriage Return, character. Value: a character with hex value '0D' or '8D'.

5.3.2. SSID - Start Session ๐Ÿ’–

okay bestie, SSID is the big intro card the Initiator sends at the start of a session ๐ŸŽ€ It's a fixed-layout message, so here's the full picture first:

   o-------------------------------------------------------------------o
   |       SSID        Start Session                                   |
   |                                                                   |
   |       Start Session Phase     Initiator <---> Responder           |
   |-------------------------------------------------------------------|
   | Pos | Field     | Description                           | Format  |
   |-----+-----------+---------------------------------------+---------|
   |   0 | SSIDCMD   | SSID Command 'X'                      | F X(1)  |
   |   1 | SSIDLEV   | Protocol Release Level                | F 9(1)  |
   |   2 | SSIDCODE  | Initiator's Identification Code       | V X(25) |
   |  27 | SSIDPSWD  | Initiator's Password                  | V X(8)  |
   |  35 | SSIDSDEB  | Exchange Buffer Size                  | V 9(5)  |
   |  40 | SSIDSR    | Send / Receive Capabilities (S/R/B)   | F X(1)  |
   |  41 | SSIDCMPR  | Compression Indicator (Y/N)           | F X(1)  |
   |  42 | SSIDREST  | Restart Indicator (Y/N)               | F X(1)  |
   |  43 | SSIDSPEC  | Special Logic Indicator (N)           | F X(1)  |
   |  44 | SSIDCRED  | Credit                                | V 9(3)  |
   |  47 | SSIDRSV1  | Reserved                              | F X(5)  |
   |  52 | SSIDUSER  | User Data                             | V X(8)  |
   |  60 | SSIDCR    | Carriage Return                       | F X(1)  |
   o-------------------------------------------------------------------o

Now let's go field by field ๐Ÿ’…

SSIDCMD (Command Code, Character) โœจ This is the command identifier. The value is 'X', the SSID Command identifier.

SSIDLEV (Protocol Release Level, Numeric(1)) ๐ŸŒธ The value '1' means ODETTE-FTP protocol release level 1. Future release levels will get higher numbers. The protocol release level is negotiable, and the lowest level gets selected.

SSIDCODE (Initiator's Identification Code, String(25)) ๐Ÿซถ Format: See Identification Code (Section 5.4). This uniquely identifies the Initiator (sender) taking part in the ODETTE-FTP session.

SSIDPSWD (Password, String(8)) ๐Ÿ” This is the key used to authenticate the sender. It's assigned by bilateral agreement.

SSIDSDEB (Exchange Buffer Size, Numeric(5)) ๐Ÿ“ Minimum: 128 and Maximum: 99999. This is the length, in octets, of the largest Exchange Buffer the location can accept. The length includes the command octet but does not include the Stream Transmission Header. After negotiation, the smallest size will be selected.

SSIDSR (Send / Receive Capabilities, Character) ๐Ÿฆ‹ The value 'S' means the location can only send files. 'R' means it can only receive files. 'B' means it can do both. Sending and receiving get serialised during the session, so parallel sessions will not take place. An error occurs if adjacent locations both specify the send or receive capability.

SSIDCMPR (Compression Indication, Character) ๐ŸŒˆ The value 'Y' means the location can handle compressed data. 'N' means it can not. Compression is only used if both locations support it. The compression mechanism is described in Section 6.2.

SSIDREST (Restart Indication, Character) ๐Ÿ” The value 'Y' means the location can handle restarting a partially transmitted file. 'N' means it can not restart a file.

SSIDSPEC (Special Logic Indication, Character) ๐Ÿงš The only valid value is 'N', and that's only for TCP. The Special Logic extensions are only useful in an X.25 environment and are not supported for TCP/IP.

SSIDCRED (Credit, Numeric(3)) ๐Ÿ’œ Maximum: 999. This is the number of consecutive Data Exchange Buffers the Speaker sends before it MUST wait for a Credit (CDT) command from the Listener. The credit value only applies to Data flow in the Data Transfer phase.

The Speaker's available credit gets set to SSIDCRED when it receives a Start File Positive Answer (SFPA) command from the Listener. It gets zeroed by the End File (EFID) command.

After negotiation, the smallest size MUST be selected in the Responder's answer, or a protocol error will abort the session. This is the negotiation of the "credit-window-size" parameter:

             Window Size m  -- SSID ------------>
                            <------------ SSID --  Window Size n
                                                   (n less or equal m)
             Note: negotiated value will be "n".

SSIDRSV1 (Reserved, String(5)) ๐ŸŽ€ This field is reserved for future use.

SSIDUSER (User Data, String(8)) ๐ŸŒธ The ODETTE-FTP is allowed to use this in any way it likes. If it goes unused, it SHOULD be initialised to spaces. A bilateral agreement is expected to exist about what the data means.

SSIDCR (Carriage Return, Character) ๐Ÿ’… The value is the character with hex value '0D' or '8D'.


5.3.3. SFID - Start File ๐Ÿฆ‹

SFID is the message that kicks off a Virtual File transfer, so this one carries all the file details ๐Ÿ“

   o-------------------------------------------------------------------o
   |       SFID        Start File                                      |
   |                                                                   |
   |       Start File Phase           Speaker ----> Listener           |
   |-------------------------------------------------------------------|
   | Pos | Field     | Description                           | Format  |
   |-----+-----------+---------------------------------------+---------|
   |   0 | SFIDCMD   | SFID Command, 'H'                     | F X(1)  |
   |   1 | SFIDDSN   | Virtual File Dataset Name             | V X(26) |
   |  27 | SFIDRSV1  | Reserved                              | F X(9)  |
   |  36 | SFIDDATE  | Virtual File Date stamp, (YYMMDD)     | V X(6)  |
   |  42 | SFIDTIME  | Virtual File Time stamp, (HHMMSS)     | V X(6)  |
   |  48 | SFIDUSER  | User Data                             | V X(8)  |
   |  56 | SFIDDEST  | Destination                           | V X(25) |
   |  81 | SFIDORIG  | Originator                            | V X(25) |
   | 106 | SFIDFMT   | File Format, (F/V/U/T)                | F X(1)  |
   | 107 | SFIDLRECL | Maximum Record Size                   | V 9(5)  |
   | 112 | SFIDFSIZ  | File Size, 1K blocks                  | V 9(7)  |
   | 119 | SFIDREST  | Restart Position                      | V 9(9)  |
   o-------------------------------------------------------------------o

Here's the breakdown ๐ŸŒท

SFIDCMD (Command Code, Character) โœจ The value is 'H', the SFID Command identifier.

SFIDDSN (Virtual File Dataset Name, String(26)) ๐Ÿ“‚ This is the dataset name of the Virtual File being transferred, assigned by bilateral agreement. No general structure is defined for this attribute. Check out Virtual Files - Identification (Section 1.5.2) for more.

SFIDRSV1 (Reserved, String(9)) ๐ŸŽ€ This field is reserved for future use.

SFIDDATE (Virtual File Date stamp, String(6)) ๐Ÿ“… Format: 'YYMMDD'. That's 6 decimal digits for the year, month and day, respectively [ISO-8601]. The Virtual File's Originator assigns this stamp to show when the file was made available for transmission. See Virtual Files - Identification (Section 1.5.2).

SFIDTIME (Virtual File Time stamp, String(6)) โฐ Format: 'HHMMSS'. That's 6 decimal digits for the hours, minutes and seconds, respectively [ISO-8601]. The Virtual File's Originator assigns this stamp to show when the file was made available for transmission. See Virtual Files - Identification (Section 1.5.2).

SFIDUSER (User Data, String(8)) ๐ŸŒธ The ODETTE-FTP is allowed to use this in any way it likes. If it goes unused, it SHOULD be initialised to spaces. A bilateral agreement is expected to exist about what the data means.

SFIDDEST (Destination, String(25)) ๐Ÿ’Œ Format: See Identification Code (Section 5.4). This is the Final Recipient of the Virtual File. It's the location that will look into the Virtual File content and perform mapping functions. It's also the location that creates the End to End Response (EERP) command for the received file.

SFIDORIG (Originator, String(25)) ๐Ÿง Format: See Identification Code (Section 5.4). This is the Originator of the Virtual File, meaning the location that created (mapped) the data for transmission.

SFIDFMT (File Format, Character) ๐ŸŒˆ The values are 'F' for Fixed format binary file, 'V' for Variable format binary file, 'U' for Unstructured binary file, and 'T' for Text. This is the Virtual File format, and it's used to calculate the restart position (Section 1.5.3).

SFIDLRECL (Maximum Record Size, Numeric(5)) ๐Ÿ“ Maximum: 99999. This is the length in octets of the longest logical record that may be transferred to a location. Only user data is included. If SFIDFMT is 'T' or 'U', then this attribute MUST be set to '00000'.

SFIDFSIZ (File Size, Numeric(7)) ๐Ÿ’พ Maximum: 9999999. This is the space, in 1K (1024 octet) blocks, required at the Originator location to store the Virtual File. It's only meant to be a good estimate of the Virtual File size.

SFIDREST (Restart Position, Numeric(9)) ๐Ÿ” Maximum: 999999999. This is the Virtual File restart position. The count represents:

  • The Record Number if SSIDFMT is 'F' or 'V'.
  • The file offset in 1K (1024 octet) blocks if SSIDFMT is 'U' or 'T'.

The count expresses the transmitted user data, meaning before compression, with the header not included. After negotiation between adjacent locations, retransmission will start at the lowest value. ๐Ÿ’–

5.3.4. SFPA - Start File Positive Answer โœจ

o-------------------------------------------------------------------o
|       SFPA        Start File Positive Answer                      |
|                                                                   |
|       Start File Phase           Speaker <---- Listener           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | SFPACMD   | SFPA Command, '2'                     | F X(1)  |
|   1 | SFPAACNT  | Answer Count                          | V 9(9)  |
o-------------------------------------------------------------------o

Okay so SFPA is the Listener saying "yes, go ahead" to a Start File ๐Ÿ’Œ It's giving "I'm ready and I'm listening" ๐ŸŽ€

SFPACMD (Command Code, Character) ๐Ÿฆ‹ Value: '2', the SFPA Command identifier.

SFPAACNT (Answer Count, Numeric(9)) ๐Ÿงฎ The Listener must enter a count lower or equal to the restart count the Speaker put in the Start File (SFID) command. The count tells you how much user data was received. If restart facilities are not available, a count of zero must be specified. So no restart? Zero, bestie, zero ๐Ÿ™ˆ

5.3.5. SFNA - Start File Negative Answer

o-------------------------------------------------------------------o
|       SFNA        Start File Negative Answer                      |
|                                                                   |
|       Start File Phase           Speaker <---- Listener           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | SFNACMD   | SFNA Command, '3'                     | F X(1)  |
|   1 | SFNAREAS  | Answer Reason                         | F 9(2)  |
|   3 | SFNARRTR  | Retry Indicator, (Y/N)                | F X(1)  |
o-------------------------------------------------------------------o

SFNA is the opposite energy ๐Ÿ’€ The Listener is saying "nah, not today," and it comes with receipts ๐Ÿงพ

SFNACMD (Command Code, Character) ๐Ÿฆ‹ Value: '3', the SFNA Command identifier.

SFNAREAS (Answer Reason, Numeric(2)) ๐Ÿ™…โ€โ™€๏ธ This is the reason why the transmission can not proceed, and the possible values are:

Value: '01'  Invalid filename.
       '02'  Invalid destination.
       '03'  Invalid origin.
       '04'  Storage record format not supported.
       '05'  Maximum record length not supported.
       '06'  File size is too big.
       '10'  Invalid record count.
       '11'  Invalid byte count.
       '12'  Access method failure.
       '13'  Duplicate file.
       '99'  Unspecified reason.

SFNARRTR (Retry Indicator, Character) ๐Ÿ” The possible values are:

Value: 'N'  Transmission should not be retried.
       'Y'  The transmission may be retried latter.

This one is the Listener telling the Speaker whether it should try again later, usually because of a temporary thing on the Listener's side, like running out of storage space. It should be used together with the Answer Reason code (SFNAREAS) ๐Ÿง 

An invalid file name error can happen because of a problem mapping the Virtual File onto a real file, and those problems can not always be fixed right away ๐Ÿ˜ญ So it is recommended that when an SFNA with Retry = Y is received, the User Monitor attempts to retransmit the relevant file in a subsequent session. Patience is a whole vibe ๐ŸŒธ

5.3.6. DATA - Data Exchange Buffer

o-------------------------------------------------------------------o
|       DATA        Data Exchange Buffer                            |
|                                                                   |
|       Data Transfer Phase        Speaker ----> Listener           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | DATACMD   | DATA Command, 'D'                     | F X(1)  |
|   1 | DATABUF   | Data Exchange Buffer payload          | V X(n)  |
o-------------------------------------------------------------------o

This is where the actual data goes, the main event ๐ŸŽฌ

DATACMD (Command Code, Character) ๐Ÿฆ‹ Value: 'D', the DATA Command identifier.

DATABUF (Data Exchange Buffer payload, String(n)) ๐Ÿ“ฆ A variable length buffer that holds the data payload. The Data Exchange Buffer is described in Section 6, so go check that one out ๐Ÿ‘€

5.3.7. CDT - Set Credit

o-------------------------------------------------------------------o
|       CDT         Set Credit                                      |
|                                                                   |
|       Data Transfer Phase        Speaker <---- Listener           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | CDTCMD    | CDT Command, 'C'                      | F X(1)  |
|   1 | CDTRSV1   | Reserved                              | F X(2)  |
o-------------------------------------------------------------------o

CDT is the credit one, and it's lowkey a flex ๐Ÿ’ณ

CDTCMD (Command Code, Character) ๐Ÿฆ‹ Value: 'C', the CDT Command identifier.

CDTRSV1 (Reserved, String(2)) ๐Ÿซ™ This field is reserved for future use, so just keep it in your back pocket for now โœจ

5.3.8. EFID - End File

o-------------------------------------------------------------------o
|       EFID        End File                                        |
|                                                                   |
|       End File Phase             Speaker ----> Listener           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | EFIDCMD   | EFID Command, 'T'                     | F X(1)  |
|   1 | EFIDRCNT  | Record Count                          | V 9(9)  |
|  10 | EFIDUCNT  | Unit Count                            | V 9(12) |
o-------------------------------------------------------------------o

EFID is the wrap-up, the "and that's a whole file" moment ๐ŸŽ€

EFIDCMD (Command Code, Character) ๐Ÿฆ‹ Value: 'T', the EFID Command identifier.

EFIDRCNT (Record Count, Numeric(9)) ๐Ÿ“Š

Maximum: 999999999

For SSIDFMT 'F' or 'V', this is the exact record count. For SSIDFMT 'U' or 'T', it's zeros. The count expresses the real size of the file, before compression, and the header is not included. The total count is always used, even during restart processing, no exceptions ๐Ÿ’…

EFIDUCNT (Unit Count, Numeric(12)) ๐Ÿ”ข

Maximum: 999999999999

This is the exact number of units (octets) transmitted. The count expresses the real size of the file, and the total count is always used, even during restart processing ๐Ÿซถ

5.3.9. EFPA - End File Positive Answer

o-------------------------------------------------------------------o
|       EFPA        End File Positive Answer                        |
|                                                                   |
|       End File Phase             Speaker <---- Listener           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | EFPACMD   | EFPA Command, '4'                     | F X(1)  |
|   1 | EFPACD    | Change Direction Indicator, (Y/N)     | F X(1)  |
o-------------------------------------------------------------------o

EFPA is the Listener's "yep, we're done, and also can we swap roles?" ๐Ÿ”„

EFPACMD (Command Code, Character) ๐Ÿฆ‹ Value: '4', the EFPA Command identifier.

EFPACD (Change Direction Indicator, Character) ๐Ÿ™‹โ€โ™€๏ธ

Value: 'N'  Change direction not requested.
       'Y'  Change direction requested.

This parameter lets the Listener ask the Speaker for a Change Direction (CD) command. Ask and you shall receive ๐Ÿ‘‘

5.3.10. EFNA - End File Negative Answer

o-------------------------------------------------------------------o
|       EFNA        End File Negative Answer                        |
|                                                                   |
|       End File Phase             Speaker <---- Listener           |
|-------------------------------------------------------------------|
| Pos | Field     | Description                           | Format  |
|-----+-----------+---------------------------------------+---------|
|   0 | EFNACMD   | EFNA Command, '5'                     | F X(1)  |
|   1 | EFNAREAS  | Answer Reason                         | F 9(2)  |
o-------------------------------------------------------------------o

EFNA is the end-of-file version of the "nope" ๐Ÿ™ƒ Same vibe as SFNA, just at the end of the file.

EFNACMD (Command Code, Character) ๐Ÿฆ‹ Value: '5', the EFNA Command identifier.

EFNAREAS (Answer Reason, Numeric(2)) ๐Ÿ™…โ€โ™€๏ธ This is the reason why the transmission can not proceed, and the possible values are:

Value: '01'  Invalid filename.
       '02'  Invalid destination.
       '03'  Invalid origin.
       '04'  Storage record format not supported.
       '05'  Maximum record length not supported.
       '06'  File size is too big.
       '10'  Invalid record count.
       '11'  Invalid byte count.
       '12'  Access method failure.
       '13'  Duplicate file.
       '99'  Unspecified reason.

Bestie, the file part is basically finished and we're so close to the good stuff ๐ŸŒˆโœจ

5.3.11 ESID - End Session โœจ

Okay so ESID is the "we're done here, bestie" command ๐Ÿ’… It's how the session gets closed out, and it comes with a reason code so the other side knows why it's wrapping up ๐Ÿซถ

   o-------------------------------------------------------------------o
   |       ESID        End Session                                     |
   |                                                                   |
   |       End Session Phase          Speaker ----> Listener           |
   |-------------------------------------------------------------------|
   | Pos | Field     | Description                           | Format  |
   |-----+-----------+---------------------------------------+---------|
   |   0 | ESIDCMD   | ESID Command, 'F'                     | F X(1)  |
   |   1 | ESIDREAS  | Reason Code                           | F 9(2)  |
   |   3 | ESIDCR    | Carriage Return                       | F X(1)  |
   o-------------------------------------------------------------------o

ESIDCMD is the command code, and it's a character ๐Ÿ”ค

  • Value: 'F', which is the ESID Command identifier.

ESIDREAS is the reason code, a numeric(2) field ๐Ÿ”ข Here are all the reasons:

  • '00': Normal session termination.
  • '01': Command not recognised. An Exchange Buffer contains an invalid command code (1st octet of the buffer).
  • '02': Protocol violation. An Exchange Buffer contains an invalid command for the current state of the receiver.
  • '03': User code not known. A Start Session (SSID) command contains an unknown or invalid Identification Code.
  • '04': Invalid password. A Start Session (SSID) command contained an invalid password.
  • '05': Local site emergency close down. The local site has entered an emergency close down mode. Communications are being forcibly terminated. this one is serious ๐Ÿ˜ญ
  • '06': Command contained invalid data. A field within a Command Exchange buffer contains invalid data.
  • '07': Exchange Buffer size error. The length of the Exchange Buffer as determined by the Stream Transmission Header is different to the length implied by the Command Code.
  • '08': Resources not available. The request for connection has been denied due to a resource shortage. The connection attempt should be retried later.
  • '09': Time out.
  • '10': Mode or capabilities incompatible.
  • '99': Unspecified Abort code. An error was detected for which no specific code is defined.

ESIDCR is the carriage return ๐ŸŽ€

  • Value: Character with hex value '0D' or '8D'.

5.3.12 CD - Change Direction ๐Ÿฆ‹

Next up is CD, the "switch roles, it's my turn" command. It shows up in the Start File, End File and End Session phases, and it's the one that lets the direction of the conversation flip ๐Ÿ”„ Honestly iconic energy.

   o-------------------------------------------------------------------o
   |       CD          Change Direction                                |
   |                                                                   |
   |       Start File Phase           Speaker ----> Listener           |
   |       End File Phase             Speaker ----> Listener           |
   |       End Session Phase        Initiator <---> Responder          |
   |-------------------------------------------------------------------|
   | Pos | Field     | Description                           | Format  |
   |-----+-----------+---------------------------------------+---------|
   |   0 | CDCMD     | CD Command, 'R'                       | F X(1)  |
   o-------------------------------------------------------------------o

CDCMD is the command code, a character ๐Ÿ’œ

  • Value: 'R', which is the CD Command identifier.

5.3.13 EERP - End to End Response ๐Ÿ’Œ

EERP is the "got it, here's proof" message. It's the End to End Response, and it's basically the receiver telling the sender that the Virtual File made it to the final recipient ๐Ÿฅน It's giving closure.

   o-------------------------------------------------------------------o
   |       EERP        End to End Response                             |
   |                                                                   |
   |       Start File Phase           Speaker ----> Listener           |
   |       End File Phase             Speaker ----> Listener           |
   |-------------------------------------------------------------------|
   | Pos | Field     | Description                           | Format  |
   |-----+-----------+---------------------------------------+---------|
   |   0 | EERPCMD   | EERP Command, 'E'                     | F X(1)  |
   |   1 | EERPDSN   | Virtual File Dataset Name             | V X(26) |
   |  27 | EERPRSV1  | Reserved                              | F X(9)  |
   |  36 | EERPDATE  | Virtual File Date stamp, (YYMMDD)     | V X(6)  |
   |  42 | EERPTIME  | Virtual File Time stamp, (HHMMSS)     | V X(6)  |
   |  48 | EERPUSER  | User Data                             | V X(8)  |
   |  56 | EERPDEST  | Destination                           | V X(25) |
   |  81 | EERPORIG  | Originator                            | V X(25) |
   o-------------------------------------------------------------------o

EERPCMD is the command code, a character โœจ

  • Value: 'E', which is the EERP Command identifier.

EERPDSN is the Virtual File Dataset Name, a String(26) ๐Ÿ“ The name is assigned by bilateral agreement, which means both sides agree on it ahead of time. There's no general structure defined for it. See Virtual Files - Identification (Section 1.5.2).

EERPRSV1 is reserved, a String(9). It's set aside for future use, so hands off ๐Ÿ™…โ€โ™€๏ธ

EERPDATE is the Virtual File Date stamp, a String(6) ๐Ÿ“…

  • Format: 'YYMMDD', which is 6 decimal digits for the year, month and day respectively [ISO-8601].
  • It's the date stamp the Virtual File's Originator put on it, showing when the file was made available for transmission. See Virtual Files - Identification (Section 1.5.2).

EERPTIME is the Virtual File Time stamp, a String(6) โฐ

  • Format: 'HHMMSS', which is 6 decimal digits for hours, minutes and seconds respectively [ISO-8601].
  • It's the time stamp the Virtual File's Originator assigned, showing when the file was made available for transmission. See Virtual Files - Identification (Section 1.5.2).

EERPUSER is User Data, a String(8) ๐ŸŽ€ The ODETTE-FTP can use it in any way. If it's unused, it should be initialised to spaces. It's expected that there's a bilateral agreement about what the data means.

EERPDEST is the Destination, a String(25) ๐Ÿ“ฌ

  • Format: See Identification Code (Section 5.4).
  • It's the Originator of the Virtual File, meaning the location that created (mapped) the data for transmission.

EERPORIG is the Originator, a String(25) ๐Ÿงš

  • Format: See Identification Code (Section 5.4).
  • It's the Final Recipient of the Virtual File. This is the location that will look into the Virtual File content and perform mapping functions. It's also the location that creates the EERP for the received file.

5.3.14 RTR - Ready To Receive ๐ŸŒธ

RTR is the "I'm ready, send it over" message ๐Ÿš€ It goes from the Responder back to the Initiator in the Start File and End File phases, so the sender knows it can go ahead.

   o-------------------------------------------------------------------o
   |       RTR         Ready To Receive                                |
   |                                                                   |
   |       Start File Phase         Initiator <---- Responder          |
   |       End File Phase           Initiator <---- Responder          |
   |-------------------------------------------------------------------|
   | Pos | Field     | Description                           | Format  |
   |-----+-----------+---------------------------------------+---------|
   |   0 | RTRCMD    | RTR Command, 'P'                      | F X(1)  |
   o-------------------------------------------------------------------o

RTRCMD is the command code, a character ๐Ÿซง

  • Value: 'P', which is the RTR Command identifier.

5.4 Identification Code ๐Ÿชช

Okay so every party in an ODETTE-FTP session needs a proper ID. The Initiator (sender) and Responder (receiver) are each uniquely identified by an Identification Code based on [ISO 6523], Structure for the Identification of Organisations (SIO) ๐ŸŒ While the session is going, the two locations are considered adjacent, so they're basically right next to each other for the whole transmission.

The SIO has the following format:

   o-------------------------------------------------------------------o
   | Pos | Field     | Description                           | Format  |
   |-----+-----------+---------------------------------------+---------|
   |   0 | SIOOID    | ODETTE Identifier                     | F X(1)  |
   |   1 | SIOICD    | International Code Designator         | V 9(4)  |
   |   5 | SIOORG    | Organisation Code                     | V X(14) |
   |  19 | SIOCSA    | Computer Sub-Address                  | V X(6)  |
   o-------------------------------------------------------------------o

SIOOID is the ODETTE Identifier, a character ๐Ÿฆ‹

  • Value: 'O' indicates an ODETTE assigned Organisation Identifier. Other values may be used for non-ODETTE codes.

SIOICD is the International Code Designator, a String(4). It's a code that forms part of the Organisation Identifier.

SIOORG is the Organisation Code, a String(14). It's also a code that forms part of the Organisation Identifier. This field may contain the letters A to Z, the digits 0 to 9, space and hyphen characters ๐Ÿ”ค

SIOCSA is the Computer Sub-Address, a String(6) ๐Ÿ’ป It's a locally assigned address that uniquely identifies a system within an organisation (defined by an Organisation Identifier).


6. ODETTE-FTP Data Exchange Buffer ๐Ÿ“ฆ

6.1 Overview ๐ŸŒˆ

Okay, the vibe here is that Virtual Files get sent by mapping their records into Data Exchange Buffers โœจ The maximum buffer length gets negotiated between the ODETTE-FTP entities through the Start Session (SSID) commands, which get swapped during the Start Session Phase of the protocol. The format is based on the Network Independent File Transfer Protocol [NIFTP] ๐Ÿ’–

Virtual File records can be any length, which is so flexible ๐Ÿ™Œ There's also a simple compression scheme for strings of repeated characters, so you don't have to send the same character over and over again ๐Ÿซถ

If you want to see the Data Exchange Buffer in action, check out Appendix A ๐ŸŽ€

6.2. Data Exchange Buffer Format ๐ŸŽ€

Okay so for sending Virtual File records, the data gets split into Subrecords, and every single one is preceded by a one octet Subrecord Header ๐Ÿ’…

The Data Exchange Buffer is made up of the initial Command character, followed by the Subrecords, like this:

      o--------------------------------------------------------
      | C | H |           | H |           | H |           |   /
      | M | D | SUBRECORD | D | SUBRECORD | D | SUBRECORD |  /_
      | D | R |           | R |           | R |           |   /
      o-------------------------------------------------------

CMD

The Data Exchange Buffer Command Character, 'D'. ๐Ÿ’–

HDR

This is the one octet Subrecord Header, and it's laid out like this:

          0   1   2   3   4   5   6   7
        o-------------------------------o
        | E | C |                       |
        | o | F | C O U N T             |
        | R |   |                       |
        o-------------------------------o

Bits

0 End of Record Flag ๐Ÿฆ‹ Set to indicate that the next subrecord is the last subrecord of the current record.

Unstructured files are transmitted as a single record, and in this case the flag acts as an end of file marker.

1 Compression Flag ๐ŸŒธ Set to indicate that the next subrecord is compressed.

2-7 Subrecord Count ๐Ÿงš This is the number of octets in the Virtual File represented by the next subrecord, expressed as a binary value.

For uncompressed data this is simply the length of the subrecord.

For compressed data this is the number of times that the single octet in the following subrecord must be inserted in the Virtual File.

Since six bits are available, the next subrecord may represent between 0 and 63 octets of the Virtual File. โœจ


6.3. Buffer Filling Rules ๐Ÿงฉ

An Exchange Buffer may be any length up to the value negotiated in the Start Session exchange. ๐Ÿ’œ

Virtual File records may be concatenated within one Exchange Buffer, or split across a number of buffers. ๐Ÿ“

Here's the big one: a subrecord is never split between two Exchange Buffers. ๐Ÿ™ˆ If the remaining space in the current Exchange Buffer is insufficient to contain the next 'complete' subrecord, one of the following strategies should be used:

  1. Truncate the Exchange Buffer, and put the complete subrecord (preceded by its header octet) in a new Exchange Buffer.
  2. Split the subrecord into two, filling the remainder of the Exchange Buffer with the first new subrecord and starting a new Exchange Buffer with the second.

A record of length zero may appear anywhere in the Exchange Buffer. ๐Ÿซถ

A subrecord of length zero may appear anywhere in the record and/or the Exchange Buffer. ๐ŸŒˆ


7. Stream Transmission Buffer (TCP only) ๐ŸŒŠ

7.1. Introduction

Okay, history lesson but make it tea โ˜• The ODETTE-FTP was originally designed to utilise the ISO Network Service, specifically the X.25 specification. It relies on the fact that the network service will preserve the sequence and boundaries of data units transmitted through the network, and that the network service will pass the length of the data unit to the receiving ODETTE-FTP. TCP, on the other hand, offers a stream based connection which does not provide these functions. ๐Ÿ˜ญ

So to use the TCP stream without disrupting the existing ODETTE-FTP, a Stream Transmission Buffer (STB) gets created by adding a Stream Transmission Header (STH) to the start of all Command and Data Exchange Buffers before they're passed to the TCP transport service. โœจ This lets the receiving ODETTE-FTP recover the original Exchange Buffers. Iconic ๐Ÿ‘‘

STH - Stream Transmission Header
OEB - ODETTE-FTP Exchange Buffer

The Stream Transmission Buffer comprises of a STH and OEB.

o-----+-----------------+-----+--------------------+-----+------
| STH | OEB             | STH |  OEB               | STH | OEB/
o-----+-----------------+-----+--------------------+-----+----

7.2. Stream Transmission Header Format ๐ŸŽ€

The Stream Transmission Header is shown below. The fields are transmitted from left to right. ๐Ÿ’…

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |Version| Flags | Length                                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Version

Value: 0001 (binary) ๐ŸŒธ

Stream Transmission Header version number.

Flags

Value: 0000 (binary) ๐Ÿงš

Reserved for future use.

Length

Range: 5 - 100003 (decimal) ๐Ÿ“

The length of the Stream Transmission Buffer (STH+OEB).

The smallest STB is 5 octets, consisting of a 4 octet header followed by a 1 octet Exchange Buffer, such as a Change Direction (CD) command. ๐Ÿฆ‹

The maximum Exchange Buffer length that can be negotiated is 99999 octets (Section 5.3.2), giving a STB length of 100003. ๐Ÿคฏ

The length is expressed as a binary number with the most significant bit on the left.

It is expected that implementations of this protocol will follow the Internet robustness principle of being conservative in what is sent and liberal in what is accepted. ๐Ÿซถ


8. Protocol State Machine ๐Ÿง 

8.1. ODETTE-FTP State Machine

The operation of an ODETTE-FTP entity is formally defined by the State Machine presented below. There are five State and Transition tables, and for each table additional information is given in the associated Predicate and Action lists. ๐Ÿ”ฅ

The response of an ODETTE-FTP entity to the receipt of an event is defined by a Transition table entry, indexed by the Event/State intersection within the appropriate State table. ๐Ÿ’œ

Each Transition table entry defines the actions taken, events generated, and new state entered. Predicates may be used within a table entry to select the correct response on the basis of local information held by the entity. ๐Ÿงš

A transition table contains the following fields:

Index(I)    State transition index.

Predicate   A list of predicates used to select between different
            possible transitions.  The predicates are defined in the
            Predicate and Action list.

Actions     A list of actions taken by the entity.  The actions are
            defined in the Predicate and Action list.

Events      Output events generated by the entity

Next State  The new state of the entity.

8.2. Error Handling ๐Ÿ’€

The receipt of an event in a given state may be invalid for three reasons. Let's go ๐Ÿ™ˆ

  1. The case is impossible by construction of the state automata, denoted X in the State tables. For example, a timer which has not been set cannot run out.
  2. The event is the result of an error in the Network Service implementation, also denoted X in the state tables. The Network Service implementation is considered to be correct.
  3. For all other cases the event is considered to be a User Error, denoted "U" in the state tables.

The State tables define the conditions under which a User event is valid, thus preventing the generation of a protocol error by the ODETTE-FTP entity as a result of a User Monitor error. The reaction of the entity to such errors is undefined and regarded as a local implementation issue. ๐ŸŒˆ

The State tables also allow protocol errors due to the receipt of invalid Exchange Buffers to be detected. In such cases, the reaction of the entity to the error is defined. โญ

8.3. States

Okay bestie, the Command Mode is strictly a Half Duplex Flip-Flop Mode ๐Ÿฆ‹. One side talks, then the other side gets its turn. No talking over each other ๐Ÿ’…

  • A_NC_ONLY (Responder, Network Connection opened): The Responder has sent its Ready Message (SSRM) and is waiting for Start Session (SSID) from the Initiator ๐ŸŒธ
  • A_WF_CONRS (Responder Waiting for F_CONNECT_RS): The Responder has received the Initiator's Start Session (SSID) and is waiting for a response (F_CONNECT_RS) from its User Monitor ๐Ÿ‘€
  • CDSTWFCD (CD_RQ stored in WF_CD state): The User Monitor can't see the WF_CD state, so it may send a Change Direction request (F_CD_RQ) before the ODETTE-FTP receives a Change Direction (CD) command ๐Ÿ™ˆ
  • CLIP (Close Input Pending): The Listener has received an End File (EFID) command and is waiting for the Close File response (F_CLOSE_FILE_RS) from its User Monitor ๐ŸŽ€
  • CLOP (Close Out Pending): The Speaker has sent an End File (EFID) command and is waiting for an End File Answer (EFPA or EFNA) โœจ
  • ERSTWFCD (End to End Response stored in WF_CD state): Same deal as CDSTWFCD. The User Monitor can't see WF_CD, so it may send F_EERP_RQ before the ODETTE-FTP receives a Change Direction (CD) command ๐Ÿ’–
  • IDLE (Connection IDLE): Chillin' ๐Ÿงš
  • IDLELI (Idle Listener): Idle Listener, just vibing ๐ŸŒˆ
  • IDLELICD (Idle Listener, F_CD_RQ Received): The ODETTE-FTP entity has become the Listener after receiving a Change Direction request (F_CD_RQ) from the User Monitor. Receiving an End Session (ESID) is valid in this state ๐Ÿ”ฅ
  • IDLESP (Idle Speaker): Idle Speaker, also chillin' ๐Ÿ“
  • IDLESPCD (Idle Speaker, F_CD_IND Sent): The ODETTE-FTP entity has sent a Change Direction indication (F_CD_IND) to the User Monitor. A Change Direction request (F_CD_RQ) is invalid in this state ๐Ÿšซ
  • I_WF_NC (Initiator Waiting for Network Connection): The Initiator has requested a new network connection and is waiting for a Connection confirmation (N_CON_CF) from the Network Service ๐Ÿ“ก
  • I_WF_RM (Initiator Waiting for Ready Message): Before sending Start Session (SSID), the Initiator must wait for a Ready Message (SSRM) from the Responder โณ
  • I_WF_SSID (Initiator Waiting for SSID): The Initiator has sent a Start Session (SSID) command and is waiting for Start Session from the Responder ๐Ÿ’œ
  • OPI (Open Input, Data Transfer Phase): The Listener is waiting for the Speaker to send a Data Exchange buffer ๐Ÿ“ฆ
  • OPIP (Open Input Pending): The Listener has received a Start File (SFID) command and is waiting for the Start File response (F_START_FILE_RS) from its User Monitor ๐Ÿฆ‹
  • OPO (Open Out, Data Transfer Phase): The Speaker has received a Start File Positive Answer (SFPA) and is waiting for a Data (F_DATA_RQ) or Close File (F_CLOSE_FILE) request from its User Monitor ๐Ÿš€
  • OPOP (Open Out Pending): The Speaker has sent a Start File (SFID) command and is waiting for a Start File Answer (SFPA or SFNA) ๐ŸŒท
  • OPOWFC (Open Out Wait for Credit): The Speaker is waiting for a Set Credit (CDT) command before sending any more Data Exchange buffers ๐Ÿ’ณ
  • SFSTWFCD (Start File Request stored in WF_CD state): The User Monitor can't see WF_CD, so it may send a Start File request (F_START_FILE_RQ) before the ODETTE-FTP receives a Change Direction (CD) command ๐Ÿซถ
  • WF_CD (Wait for Change Direction): The Listener wants to become the Speaker and is waiting for a Change Direction (CD) command after sending an End File Positive Answer (EFPA) requesting a change of direction ๐Ÿ”„
  • WF_RTR (Wait for Ready To Receive): The Initiator has sent an End to End Response (EERP) command and must wait for Ready To Receive (RTR) from the Responder ๐Ÿ™
  • WF_NDISC (Wait for N_DISC_IND): The ODETTE-FTP has sent an End Session (ESID) command and is waiting for a Disconnection indication (N_DISC_IND) from the Network Service ๐Ÿ‘‹

8.4. Input Events

Here's everything that can walk into the state machine and knock ๐Ÿšช

   User Monitor Input Events (Section 3)

     F_DATA_RQ   F_CONNECT_RQ   F_START_FILE_RQ      F_CLOSE_FILE_RQ
     F_EERP_RQ   F_CONNECT_RS   F_START_FILE_RS(+)   F_CLOSE_FILE_RS(+)
     F_CD_RQ     F_ABORT_RQ     F_START_FILE_RS(-)   F_CLOSE_FILE_RS(-)
                 F_RELEASE_RQ

   Network Input Events (Section 2.2)

      N_CON_IND   N_CON_CF   N_DATA_IND   N_DISC_IND   N_RST_IND

   Peer ODETTE-FTP Input Events (Section 4)

      SSID   SFID   SFPA   SFNA   EFID   EFPA   EFNA
      DATA   ESID   EERP   RTR    CD     CDT    SSRM

   Internal Input Events

      TIME-OUT - Internal ODETTE-FTP timer expires.

Input event parameters are written as I.Event-name.Parameter-name inside the state table action and predicate lists. The ODETTE-FTP entity can look at them, but it can't change them ๐Ÿ‘€

8.5. Output Events

And here's everything the state machine can send back out ๐Ÿ“ค

   User Monitor Output Events (Section 3)

     F_DATA_IND  F_CONNECT_IND  F_START_FILE_IND     F_CLOSE_FILE_IND
     F_EERP_IND  F_CONNECT_CF   F_START_FILE_CF(+)   F_CLOSE_FILE_CF(+)
     F_CD_IND    F_ABORT_IND    F_START_FILE_CF(-)   F_CLOSE_FILE_CF(-)
                 F_RELEASE_IND

   Network Output Events (Section 2.2)

      N_CON_RQ   N_CON_RS   N_DATA_RQ   N_DISC_RQ

   Peer ODETTE-FTP Output Events (Section 4)

      SSID   SFID   SFPA   SFNA   EFID   EFPA   EFNA
      DATA   ESID   EERP   RTR    CD     CDT    SSRM

Output event parameters are written as O.Event-name.Parameter-name inside the state table action and predicate lists. This time the ODETTE-FTP entity can both look at them and change them ๐Ÿ› ๏ธ

8.6. Local Variables

The ODETTE-FTP entity keeps track of these variables to help the protocol run smoothly ๐Ÿง . They're written as V.Variable-name in the action and predicate lists. The entity can look at and change their values, and each one starts out undefined ๐ŸŒฑ

   Variable     Type       Comments
   ---------------------------------------------------------------------
   Buf-size     Integer    Negotiated Exchange Buffer size.
   Called-addr  Address    Used to build O.F_CONNECT_IND.Called-addr
   Calling-addr Address    To build O.F_CONNECT_IND.Calling-addr
   Compression  Yes/No     Compression in used as agreed.
   Credit_L     Integer    Listeners credit counter.
   Credit_S     Integer    Speaker's credit counter.
   Id           String     Used to build O.SSID.Id
   Mode                    Sender-only, Receiver-only, Both.
   Pswd         String     Password, used to build O.SSID.Pswd
   Req-buf      Primitive  Input event (F_XXX_RQ) stored in WF_CD state.
   Restart      Yes/No     Restart in used as agreed.
   Restart-pos  Integer    Used only during file opening.
   Window       Integer    The Credit value negotiated for the session.
   ---------------------------------------------------------------------

8.7. Local Constants

These constants describe what a particular ODETTE-FTP entity is capable of ๐Ÿ’ช. They're written as C.Constant-name in the state table action and predicate lists. The entity can look at them but can't change them ๐Ÿ”’

   Constant         Value               Comments
   ---------------------------------------------------------------------
   Cap-compression  Yes/No              Compression supported?
   Cap-init         Initiator           Must be Initiator.
                    Responder           Must be Responder.
                    Both                Can be Initiator or Responder.
   Cap-mode         Sender-only         Must be sender.
                    Receiver-only       Must be receiver.
                    Both                Can be sender or receiver.
   Max-buf-size     127 < Int < 100000  Maximum buffer size supported.
   Max-window       Int < 1000          Local maximum credit value.
   ---------------------------------------------------------------------

8.8. Session Connection State Table

8.8.1. State Table

Time for the big grid ๐Ÿฐ

   o----------------------------------------------o
   |   | Other States                             |
   |   |--------------------------------------o   |
   | S | A_WF_CONRS                           |   |
   |   |----------------------------------o   |   |
   | T | A_NC_ONLY                        |   |   |
   |   |------------------------------o   |   |   |
   | A | I_WF_SSID                    |   |   |   |
   |   |--------------------------o   |   |   |   |
   | T | I_WF_RM                  |   |   |   |   |
   |   |----------------------o   |   |   |   |   |
   | E | I_WF_NC              |   |   |   |   |   |
   |   |------------------o   |   |   |   |   |   |
   |   | IDLE             |   |   |   |   |   |   |
   |==================o---+---+---+---+---+---+---|
   |   | F_CONNECT_RQ | A | X | X | X | X | X | X |
   |   |--------------+---+---+---+---+---+---+---|
   | E | N_CON_CF     | X | C | X | X | X | X | X |
   |   |--------------+---+---+---+---+---+---+---|
   | V | SSRM         | X | X | H | X | X | X | X |
   |   |--------------+---+---+---+---+---+---+---|
   | E | SSID         | X | X | X | D | E | F | F |
   |   |--------------+---+---+---+---+---+---+---|
   | N | N_CON_IND    | B | X | X | X | X | X | X |
   |   |--------------+---+---+---+---+---+---+---|
   | T | F_CONNECT_RS | X | U | U | U | U | G | U |
   |   |--------------+---+---+---+---+---+---+---|
   |   | ESID(R=10)   | X | X | X | F | X | X | X |
   o----------------------------------------------o

8.8.2. Transition Table

Now for the letters in the grid. Each one points to a row here, telling us what to check, what to send, and where to land ๐ŸŽฏ

    I | Predicate    Actions     Output Events               Next State
   ===o=================================================================
    A | P1:                      F_ABORT_IND                 IDLE
      | not P1:      1           N_CON_RQ                    I_WF_NC
   ---+-----------------------------------------------------------------
    B | P3:                      N_DISC_RQ                   IDLE
      | not P3:                  N_CON_RS
      |                          SSRM                        A_NC_ONLY
   ---+-----------------------------------------------------------------
    C |              2                                       I_WF_RM
   ---+-----------------------------------------------------------------
    D | P2:          4,2,5       F_CONNECT_CF                IDLESP
      | not P2:      4,2         ESID(R=10)
      |                          F_ABORT_IND(R,AO=L)         WF_NDISC
   ---+-----------------------------------------------------------------
    E | P4:          4           N_DISC_RQ                   IDLE
      | not P4:                  F_CONNECT_IND               A_WF_CONRS
   ---+-----------------------------------------------------------------
    F |                          F_ABORT_IND
      |                          N_DISC_RQ                   IDLE
   ---+-----------------------------------------------------------------
    G | P2:          4,2,5       SSID                        IDLELI
      | not P2:      4,2         ESID(R=10)
      |                          F_ABORT_IND(R,AO=L)         WF_NDISC
   ---+-----------------------------------------------------------------
    H |              4,2,3       SSID                        I_WF_SSID
   ---------------------------------------------------------------------

8.8.3. Predicates and Actions โœจ

Okay so predicates are the yes-or-no checks and actions are the stuff that actually gets done. This is where the session connection logic gets real ๐Ÿ’…

Predicate P1:  (No resources available) OR
               (C.Cap-init = Responder) OR
               (C.Cap-mode = Sender-only AND
                  I.F_CONNECT_RQ.Mode = Receiver-only) OR
               (C.Cap-mode = Receiver-only AND
                  I.F_CONNECT_RQ.Mode = Sender-only)

Predicate P2:  Negotiation of (Buf-size, Restart, Compression,
                               Mode, Credit) is OK.

Predicate P3:  C.Cap-init = Initiator

Predicate P4:  Mode in SSID incompatible with C.Cap-mode

    Action 1:  Set V.Mode from (C.Cap-mode, I.F_CONNECT_RQ.Mode)
               Set V.Pswd, V.Id, V.Restart from I.F_CONNECT_RQ
               Set V.Buf-size = C.Max-buf-size
               Set V.Compression = C.Cap-compression
               Build O.N_CON_RQ

    Action 2:  Start inactivity timer

    Action 3:  Set parameters in O.SSID = from local variables

    Action 4:  Stop timer

    Action 5:  Set V.Mode, V.Restart, V.Compression, V.Buf-size,
                   V.Window = from SSID

8.9. Error and Abort State Table ๐Ÿšจ

8.9.1. State Table

Here's the grid for the error and abort states. It's giving spreadsheet energy ๐Ÿ“

   o--------------------------------------o
   |   | Other States                     |
   | S |------------------------------o   |
   | T | WF_NDISC                     |   |
   | A |--------------------------o   |   |
   | T | I_WF_NC                  |   |   |
   | E |----------------------o   |   |   |
   |   | IDLE                 |   |   |   |
   |======================o---+---+---+---|
   |   | TIME-OUT         | X | X | A | B |
   |   |------------------+---+---+---+---|
   | E | F_ABORT_RQ       | X | A | X | C |
   | V |------------------+---+---+---+---|
   | E | N_RST_IND        | X | X | A | D |
   | N |------------------+---+---+---+---|
   | T | N_DISC_IND       | X | E | F | G |
   |   |------------------+---+---+---+---|
   |   | Invalid Buffer   | X | X | H | I |
   o--------------------------------------o

8.9.2. Transition Table

Now the transition table for those letters A through I. Pay attention to the Output Events column, bestie ๐Ÿ‘‘

    I | Predicate    Actions     Output Events              Next State
   ===o=================================================================
    A |                          N_DISC_RQ                 IDLE
   ---+-----------------------------------------------------------------
    B |                          F_ABORT_IND
      |                          N_DISC_RQ                 IDLE
   ---+-----------------------------------------------------------------
    C |              1           N_DISC_RQ                 IDLE
   ---+-----------------------------------------------------------------
    D |              1           N_DISC_RQ
      |                          F_ABORT_IND               IDLE
   ---+-----------------------------------------------------------------
    E |                          F_ABORT_IND               IDLE
   ---+-----------------------------------------------------------------
    F |              1                                     IDLE
   ---+-----------------------------------------------------------------
    G |              1           F_ABORT_IND               IDLE
   ---+-----------------------------------------------------------------
    H |                                                    WF_NDISC
   ---+-----------------------------------------------------------------
    I |              1,2         ESID(R=01)
      |                          F_ABORT_IND(R,AO=L)       WF_NDISC
   ---------------------------------------------------------------------

8.9.3. Predicates and Actions

These are the two little actions that start and stop the inactivity timer. Simple, but iconic ๐Ÿฆ‹

       Action 1:  Stop inactivity timer

       Action 2:  Start inactivity timer

8.10. Speaker State Table 1 ๐ŸŽ€

8.10.1. State Table

Before the big grid, here are the abbreviations you'll need for the Speaker State table ๐Ÿงš

      F_REL_RQ(Ok)   -  F_RELEASE_RQ Reason = Normal
      F_REL_RQ(Err)  -  F_RELEASE_RQ Reason = Error

And this is the Speaker State table itself. It is LONG, so take a deep breath and bring snacks ๐Ÿ˜ญ

   o------------------------------------------------------------------o
   |   | Other State                                                  |
   |   |----------------------------------------------------------o   |
   |   | WF_NDISC                                                 |   |
   |   |------------------------------------------------------o   |   |
   |   | OPOWFC                                               |   |   |
   |   |--------------------------------------------------o   |   |   |
   |   | OPO                                              |   |   |   |
   | S |----------------------------------------------o   |   |   |   |
   |   | OPOP                                         |   |   |   |   |
   | T |------------------------------------------o   |   |   |   |   |
   |   | CDSTWFCD                                 |   |   |   |   |   |
   | A |--------------------------------------o   |   |   |   |   |   |
   |   | SFSTWFCD                             |   |   |   |   |   |   |
   | T |----------------------------------o   |   |   |   |   |   |   |
   |   | ERSTWFCD                         |   |   |   |   |   |   |   |
   | E |------------------------------o   |   |   |   |   |   |   |   |
   |   | WF_CD                        |   |   |   |   |   |   |   |   |
   |   |--------------------------o   |   |   |   |   |   |   |   |   |
   |   | WF_RTR                   |   |   |   |   |   |   |   |   |   |
   |   |----------------------o   |   |   |   |   |   |   |   |   |   |
   |   | IDLESPCD             |   |   |   |   |   |   |   |   |   |   |
   |   |------------------o   |   |   |   |   |   |   |   |   |   |   |
   |   | IDLESP           |   |   |   |   |   |   |   |   |   |   |   |
   |===+==============o---+---+---+---+---+---+---+---+---+---+---+---|
   |   | F_EERP_RQ    | A | A | W | F | W | U | U | U | U | U | U | U |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   |   | F_START_     | B | B | W | G | W | U | U | U | U | U | X | U |
   |   |   FILE_RQ    |   |   |   |   |   |   |   |   |   |   |   |   |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   |   | SFPA         | C | C | C | C | C | C | C | K | C | C | S | C |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   | E | SFNA         | C | C | C | C | C | C | C | L | C | C | S | C |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   | V | CD           | C | C | C | H | R | I | J | C | C | C | S | C |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   | E | F_DATA_RQ    | U | U | U | U | U | U | U | U | M | V | S | U |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   | N | CDT          | C | C | C | C | C | C | C | C | P | O | S | C |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   | T | F_CD_RQ      | D | U | W | T | W | U | U | U | U | U | X | U |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   |   | F_REL_RQ(Ok) | U | E | U | U | U | U | U | U | U | U | X | U |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   |   | F_REL_RQ(Err)| Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | S | Q |
   |   |--------------+---+---+---+---+---+---+---+---+---+---+---+---|
   |   | RTR          | C | C | N | C | C | C | C | C | C | C | S | C |
   o------------------------------------------------------------------o

8.10.2. Transition Table

The grid tells you where you are, and this table tells you what happens next. It's a big one, so read it in two chunks ๐Ÿ’–

    I | Predicate    Actions     Output Events              Next State
   ===o=================================================================
    A |              1,2,3       EERP                       WF_RTR
   ---+-----------------------------------------------------------------
    B | P1:                                                 UE
      | not P1:      1,2,5       SFID                       OPOP
   ---+-----------------------------------------------------------------
    C |              1,2         ESID(R=02)
      |                          F_ABORT_IND(R,AO=L)        WF_NDISC
   ---+-----------------------------------------------------------------
    D |              1,2         CD                         IDLELICD
   ---+-----------------------------------------------------------------
    E |              1,2         ESID(R=00)                 WF_NDISC
   ---+-----------------------------------------------------------------
    F |              4                                      ERSTWFCD
   ---+-----------------------------------------------------------------
    G | P1:                                                 UE
      | not P1:      6                                      SFSTWFCD
   ---+-----------------------------------------------------------------
    H |              1,2                                    IDLESP
   ---+-----------------------------------------------------------------
    I |              1,2,10      SFID                       OPOP
   ---+-----------------------------------------------------------------
    J |              1,2         CD                         IDLELICD
   ---+-----------------------------------------------------------------
    K | P2:          1,2         ESID(R=02)
      |                          F_ABORT_IND(R,AO=L)        WF_NDISC
      | not P2:      1,2,7,12    F_START_FILE_CF(+)         OPO
   ---+-----------------------------------------------------------------
    L |              1,2,8       F_START_FILE_CF(-)         IDLESP
   ---+-----------------------------------------------------------------
    M | P3:          1,2,11,13   DATA                       OPOWFC
      | not P3:      1,2,11,13   DATA                       OPO
   ---+-----------------------------------------------------------------
    N |                          Note 3                     IDLESP
   ---+-----------------------------------------------------------------
    O |              12                                     OPO
      |                                                     See Note 1
   ---+-----------------------------------------------------------------
    P | Protocol     1,2         ESID(R=02)
      | Error                    F_ABORT_IND(R,AO=L)        WF_NDISC
   ---+-----------------------------------------------------------------
    Q |              1,2         ESID(R)                    WF_NDISC
   ---+-----------------------------------------------------------------
                                                            Continued -->

    I | Predicate    Actions     Output Events              Next State
   ===o=================================================================
    R |              1,2,9       EERP                       WF_RTR
   ---+-----------------------------------------------------------------
    S |                                                     WF_NDISC
   ---+-----------------------------------------------------------------
    T |                                                     CDSTWFCD
   ---+-----------------------------------------------------------------
    U |                          User Error                 UE
   ---+-----------------------------------------------------------------
    V |                          User Error - Note 1        UE
   ---+-----------------------------------------------------------------
    W |                          User Error - Note 2        UE
   ---+-----------------------------------------------------------------
    X |                          Error
   ---------------------------------------------------------------------

8.10.3. Predicates and Actions โœจ

okay so here are the predicates for this state. they're the checks that decide what happens next ๐Ÿ‘€

  • (I.F_START_FILE_RQ.Restart-pos > 0) AND ((V.Restart = No) OR (V.Mode = Receiver-only)) is P1 ๐Ÿ™ˆ Restart was requested, but it isn't supported for this session.
  • (I.SFPA.Restart-pos > V.Restart-pos) is P2 ๐Ÿ’€ This is a protocol error, because the restart position in the SFPA acknowledgement is bigger than the position we asked for in the SFID request.
  • V.Credit_S - 1 = 0 is P3 ๐Ÿซถ The Speaker's credit is used up.

These are the actions, copied exactly:

Action 1:  Stop inactivity timer

Action 2:  Start inactivity timer

Action 3:  Build an EERP from F_EERP_RQ

Action 4:  Store F_EERP_RQ in V.Req-buf

Action 5:  Build SFID from F_START_FILE_RQ
           V.Restart-pos = I.F_START_FILE_RQ.Restart-pos

Action 6:  Store F_START_FILE_RQ in V.Req-buf

Action 7:  Build F_START_FILE_CF(+) from I.SFPA
Action 8:  Build F_START_FILE_CF(-) from I.SFNA

Action 9:  Build EERP from F_EERP_RQ stored in V.Req-buf

Action 10: Build SFID from F_START_FILE_RQ stored in V.Req-buf
           Set V.Restart-pos

Action 11: Build Exchange Buffer

Action 12: V.Credit_S = V.Window

Action 13: V.Credit_S = V.Credit_S - 1

Note 1 is the big one ๐Ÿ˜ญ In OPOWFC the Speaker literally can't send data buffers, because it's waiting for credit. The ODETTE-FTP entity might need to control how fast Data requests (F_DATA_RQ) come in from its User Monitor, so it doesn't blow up its own buffers. Any mechanism like that, plus what the entity does if a User Error happens, is a local implementation issue. Your call, bestie ๐Ÿ’…

Note 2: whether to accept this "Request/Event" while in this state is a local implementation choice ๐Ÿฆ‹ The ODETTE state tables assume this event can't happen in this state, so it counts as a user error (UE).

Note 3: it's a local matter to let the User Monitor know that the RTR has arrived, so the protocol machine is ready for the next request ๐ŸŽ€


8.11. Speaker State Table 2 ๐ŸŒธ

8.11.1. State Table

  o---------------------------------o
  | S | CLOP                        |
  | T |-------------------------o   |
  | A | OPOWFC                  |   |
  | T |---------------------o   |   |
  | E | OPO                 |   |   |
  |=====================o---+---+---|
  | E | F_CLOSE_FILE_RQ | A | E | U |
  | V |-----------------+---+---+---|
  | E | EFPA            | B | B | C |
  | N |-----------------+---+---+---|
  | T | EFNA            | B | B | D |
  o---------------------------------o

8.11.2. Transition Table

    I | Predicate    Actions     Output Events              Next State
   ===o=================================================================
    A |              1,2,5,7     EFID                       CLOP
   ---+-----------------------------------------------------------------
    B |              1,2         ESID(R=02)
      |                          F_ABORT_IND(R,AO=L)        WF_NDISC
   ---+-----------------------------------------------------------------
    C | P1:          1,2,3       F_CLOSE_FILE_CF(+,SP=No)
      |                          CD                         IDLELI
      | not P1:      1,2,4       F_CLOSE_FILE_CF(+,SP=Yes)  IDLESP
   ---+-----------------------------------------------------------------
    D |              1,2,6       F_CLOSE_FILE_CF(-)         IDLESP
   ---+-----------------------------------------------------------------
    E |                          See Note 1
   ---+-----------------------------------------------------------------
    U |                          User Error                 UE
   ---------------------------------------------------------------------

8.11.3. Predicates and Actions โœจ

  • (I.EFPA.CD-Request = Yes) AND (V.Mode = Both) is P1 ๐Ÿ’– The check for whether the CD request arrived and the mode is Both.

These are the actions:

Action 1:  Stop inactivity timer

Action 2:  Start inactivity timer

Action 3:  O.F_CLOSE_FILE_CF(+).Speaker = No

Action 4:  O.F_CLOSE_FILE_CF(+).Speaker = Yes

Action 5:  Build EFID from F_CLOSE_FILE_RQ

Action 6:  Build F_CLOSE_FILE_CF(-) from EFNA

Action 7:  Set V.Credit_S = 0

Note 1 is about the "half duplex" property of ODETTE-FTP ๐ŸŒˆ It's forbidden to send EFID while in the OPOWFC state. EFID can only be sent in the OPO state, so the ODETTE-FTP implementation has to avoid sending EFID (or receiving F_CLOSE_FILE_RQ) while in OPOWFC. Respect the half duplex, periodt ๐Ÿซถ


8.12. Listener State Table ๐Ÿฆ‹

8.12.1. State Table

  o-----------------------------------------o
  |   | CLIP                                |
  |   |---------------------------------o   |
  |   | OPI                             |   |
  | S |-----------------------------o   |   |
  | T | OPIP                        |   |   |
  | A |-------------------------o   |   |   |
  | T | IDLELICD                |   |   |   |
  | E |---------------------o   |   |   |   |
  |   | IDLELI              |   |   |   |   |
  |=====================o---+---+---+---+---|
  |   | SFID            | A | A | B | B | B |
  |   |-----------------+---+---+---+---+---|
  | E | DATA            | B | B | B | I | B |
  | V |-----------------+---+---+---+---+---|
  | E | EFID            | B | B | B | J | B |
  | N |-----------------+---+---+---+---+---|
  | T | F_START_FILE_RS | U | U | H | U | U |
  |   |-----------------+---+---+---+---+---|
  |   | F_CLOSE_FILE_RS | U | U | U | U | K |
  |   |-----------------+---+---+---+---+---|
  |   | CD              | C | B | B | B | B |
  |   |-----------------+---+---+---+---+---|
  |   | ESID R=Normal   | D | F | D | D | D |
  |   |-----------------+---+---+---+---+---|
  |   | ESID R=Error    | D | D | D | D | D |
  |   |-----------------+---+---+---+---+---|
  |   | EERP            | E | G | B | B | B |
  o-----------------------------------------o

8.12.2. Transition Table

    I | Predicate    Actions       Output Events             Next State
   ===o=================================================================
    A | P1:          1,2           ESID(R=02)
      |                            F_ABORT_IND(R,AO=L)       WF_NDISC
      | not P1:      1,2,3         F_START_FILE_IND          OPIP
   ---+-----------------------------------------------------------------
    B |              1,2           ESID(R=02)
      |                            F_ABORT_IND(R,AO=L)       WF_NDISC
   ---+-----------------------------------------------------------------
    C |              1,2           F_CD_IND                  IDLESPCD
   ---+-----------------------------------------------------------------
    D |              1             F_ABORT_IND(Received
      |                               ESID Reason,AO=D)
      |                            N_DISC_RQ                 IDLE
   ---+-----------------------------------------------------------------
    E |              4             F_EERP_IND
      |              8             See Note 2
      |                            RTR                       IDLELI
   ---+-----------------------------------------------------------------
    F |              1             F_RELEASE_IND
      |                            N_DISC_RQ                 IDLE
   ---+-----------------------------------------------------------------
    G |                            F_EERP_IND
      |              8             See Note 2
      |                            RTR                       IDLELI
   ---+-----------------------------------------------------------------
    H | P4:                        User Error                UE
      | P2,not P4:   1,2           SFPA                      OPI
      | not(P2,P4):  1,2           SFNA                      IDLELI
   ---+-----------------------------------------------------------------
    I | P5:          1,2           ESID(R=02)
      |                            F_ABORT_IND(R,A0=L)       WF_NDISC
      | not(P5,P6):  1,2,5         F_DATA_IND                OPI
      | not P5,P6:   1,2           F_DATA_IND
      |              6,7           See Note 1
      |                            CDT                       OPI
   ---+-----------------------------------------------------------------
    J |              1,2           F_CLOSE_FILE_IND          CLIP
   ---+-----------------------------------------------------------------
    K | P2,P3:       1,2           EFPA(CD-Req)              WF_CD
      | P2,not P3:   1,2           EFPA(no CD)               IDLELI
      | not P2:      1,2           EFNA                      IDLELI
   ---+-----------------------------------------------------------------
    U |                            User Error                UE
   ---------------------------------------------------------------------

8.12.3. Predicates and Actions ๐Ÿ’…

Here are the predicates. Each one is a check the Listener runs before deciding what to do:

  • (I.SFID.Restart-pos > 0) AND (V.Restart = No) is P1 ๐Ÿ™ˆ Note: this is an invalid Start File command.
  • P2 is just "Positive Response" ๐ŸŒธ
  • I.F_CLOSE_FILE_RS(+).Speaker = Yes is P3 ๐Ÿงš
  • I.F_START_FILE_RS(+).Restart-pos > V.Restart is P4 ๐Ÿ‘‘
  • V.Credit_L - 1 < 0 is P5 ๐Ÿ’€ Note: this is a protocol error, because the Speaker has gone past its available transmission credit.
  • V.Credit_L - 1 = 0 is P6 ๐Ÿ“ Note: the Speaker's credit has to be reset before it can send any more Data Exchange buffers.

These are the actions:

Action 1:  Stop inactivity timer.

Action 2:  Start inactivity timer

Action 3:  Build F_START_FILE_IND from I.SFID
           V.Restart-pos = I.SFID.Restart-pos

Action 4:  Build F_EERP_IND from I.EERP

Action 5:  V.Credit_L = V.Credit_L - 1

Action 6:  Wait for sufficient resources to receive up to
           V.Window Data Exchange Buffers.

Action 7:  V.Credit_L = V.Window

Action 8:  Wait for resources required to process a new EERP.

Note 1 is all about flow control on the receiving end ๐ŸŒฟ The ODETTE-FTP Listener has to send new credit to the Speaker on a regular basis. When it does that depends on three things:

  1. How much the User Monitor can take in to receive data.
  2. How many buffers ODETTE-FTP has available.
  3. The Speaker's available credit, which must be equal to zero.

Note 2: usually the ODETTE-FTP Listener sends the RTR right after it gets the EERP โœจ If it needs to, it can hold off on the RTR until the resources needed to process a new EERP are ready.

8.13 Example โœจ

okay so picture an ODETTE-FTP entity that has already sent a Start File (SFID) command and is now chilling in the Open Out Pending (OPOP) state ๐ŸŽ€. Its reaction when a Positive Answer (SFPA) comes back is written up in Speaker State Table 1, where transition 'K' is the one that kicks in. Here's how it plays out:

      if (I.SFPA.Restart-pos > V.Restart-pos) then
      begin                                       // invalid restart
         Actions:   Stop inactivity timer,        // reset timer
                    Start inactivity timer;
         Output:    ESID(R=02),                   // to peer ODETTE-FTP
                    F_ABORT_IND(R,AO=L);          // to user monitor
         New State: WF_NDISC;
      end
      else begin
         Actions:   Stop inactivity timer,        // reset timer
                    Start inactivity timer;
                    Build F_START_FILE_CF(+) from I.SFPA
                    V.Credit_S = V.Window         // initialise credit
         Output:    F_START_FILE_CF(+);           // to user monitor
         New State: OPO;
      end

so the ODETTE-FTP checks the restart position inside the SFPA command it just got ๐Ÿ‘€. If that position is invalid, it's a no-go: it aborts the session by sending an End Session (ESID) command to its peer, plus an Abort indication (F_ABORT_IND) to its User Monitor ๐Ÿ’€. If the restart position checks out, it builds a Start File confirmation (F_START_FILE_CF), sends that up to the User Monitor, initialises the credit window, and moves into the Open Out (OPO) state ๐Ÿ’…โœจ

9. Security Considerations ๐Ÿ”

not gonna lie, this part is serious ๐Ÿ˜ญ. ODETTE-FTP sends user identity and password info in clear text. So it's recommended that a lower layer (session, network or linkage) security protocol protects the session, so nobody can casually harvest identities off the wire ๐Ÿ™ˆ๐Ÿ”’

Appendix A. Virtual File Mapping Example ๐Ÿงš

this appendix shows how a Virtual File gets mapped into a bunch of ODETTE-FTP Data Exchange Buffers, and how each Stream Transmission Buffer is made from a Data Exchange Buffer with a Stream Transmission Header stuck on the front ๐Ÿฆ‹

every line in this extract from 'The Hunting of the Snark' by Lewis Carroll [SNARK] is treated as its own record in a file of variable length records. it's not a text file, so CR/LF record separators aren't used at all, and the blank line is just a zero length record ๐Ÿ“–

      "It's a Snark!" was the sound that first came to their ears,
           And seemed almost too good to be true.
      Then followed a torrent of laughter and cheers:
           Then the ominous words "It's a Boo-"

      Then, silence.  Some fancied they heard in the air
           A weary and wandering sigh
      Then sounded like "-jum!" but the others declare
           It was only a breeze that went by.

assuming a minimum exchange buffer length of 128 octets has been negotiated, mapping the text into Stream Transmission Buffers could look like this ๐ŸŒธ

   Stream Transmission Buffer 1

      Text  :  ....D."It' s a Snark! " was the  sound that  first cam
      Hex-H :  10084B2472 7262566762 2276727662 7676627667 2667772666
      Hex-L :  00044C2947 30103E12B1 2071304850 3F5E404814 069234031D
      Key   :  ----D!.... .......... .......... .......... ..........

      Text  :  e to their  ears,. .A nd seemed  almost too  good to b
      Hex-H :  6276276667 26677242A4 6627666662 6666772766 2666627626
      Hex-L :  504F048592 05123C5061 E40355D540 1CDF3404FF 07FF404F02
      Key   :  .......... ......!.!. .......... .......... ..........

      Text  :  e true..Th en followe d a torren t
      Hex-H :  6277762156 6626666676 6262767766 72
      Hex-L :  504255E848 5E06FCCF75 40104F225E 40
      Key   :  .......!.. .......... .......... ..

      Text  :  ....D.of l aughter an d cheers:.  .Then the  ominous w
      Hex-H :  1007496626 6766767266 6266667734 2A56662766 2666667727
      Hex-L :  000847F60C 157845201E 40385523A5 04485E0485 0FD9EF5307
      Key   :  ----D!.... .......... .........! .!........ ..........

      Text  :  ords "It's  a Boo-".. Then, sile nce.  Some  fancied t
      Hex-H :  6767224727 262466228B 5666227666 6662225666 2666666627
      Hex-L :  F243029473 0102FFD202 485EC039C5 E35E003FD5 061E395404
      Key   :  .......... ........!! .......... .......... ..........

      Text  :  hey heard  in the air
      Hex-H :  6672666762 6627662667
      Hex-L :  8590851240 9E04850192
      Key   :  .......... ..........

   Stream Transmission Buffer 3

      Text  :  ....D. .A  weary and  wandering  sigh.Then  sounded li
      Hex-H :  1007442942 7667726662 7666676662 7666B56662 7676666266
      Hex-L :  0008450A10 7512901E40 71E4529E70 39780485E0 3F5E4540C9
      Key   :  ----D!.!.. .......... .......... ....!..... ..........

      Text  :  ke "-jum!"  but the o thers decl are. .It w as only a
      Hex-H :  6622267622 2677276626 7667726666 67642A4727 6726667262
      Hex-L :  B502DA5D12 025404850F 485230453C 1255029407 130FEC9010
      Key   :  .......... .......... .......... ...!.!.... ..........

      Text  :  breeze tha t went by.
      Hex-H :  6766762766 7276672672
      Hex-L :  2255A50481 4075E4029E
      Key   :  .......... ..........

   Notes:
      Hex-H       High order bits of octet
      Hex-L       Low order bits of octet
      Key:  ----  Stream Transmission Header
            D     Data Exchange Buffer command code 'D'
            !     Subrecord header octet
            .     Place holder
      All headers are represented with a period in the Text line.

every Data Exchange Buffer gets a Stream Transmission Header in front of it ๐ŸŽ€

the first Data Exchange Buffer is 128 octets long, and the last record in it keeps going into the second buffer ๐Ÿƒโ€โ™€๏ธ

the second Data Exchange Buffer gets chopped off at 116 octets so it ends at the end of a record ๐Ÿ’…. the next record then sits completely inside the third buffer. that's an alternative to spanning the record across the first and second buffers, like we saw above ๐Ÿฆ‹

the blank line gets encoded as one header octet of '80' hex, which means a zero length subrecord with the end of record flag set ๐ŸŒˆ

and the indented lines have been compressed ๐Ÿซถ

Appendix B. ISO 646 Character Subset ๐Ÿ”ค

here's the ISO 646 character subset laid out as a grid, bit patterns down the side and columns across the top ๐Ÿ’œ

   o-----------------------------------------------------------------o
   |            |   7| 0   | 0   | 0   | 0   | 1   | 1   | 1   | 1   |
   |            | B -+-----+-----+-----+-----+-----+-----+-----+-----|
   |            | I 6|  0  |  0  |  1  |  1  |  0  |  0  |  1  |  1  |
   |            | T -+-----+-----+-----+-----+-----+-----+-----+-----|
   |            |   5|   0 |   1 |   0 |   1 |   0 |   1 |   0 |   1 |
   |            |----+-----+-----+-----+-----+-----+-----+-----+-----|
   |            |    |     |     |     |     |     |     |     |     |
   |            |    |     |     |     |     |     |     |     |     |
   |------------|    |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |
   |    BIT     |    |     |     |     |     |     |     |     |     |
   | 4  3  2  1 |    |     |     |     |     |     |     |     |     |
   |============o====o=====+=====+=====+=====+=====+=====+=====+=====|
   | 0  0  0  0 |  0 |     |     | SP  |  0  |     |  P  |     |     |
   |------------|----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 0  0  0  1 |  1 |     |     |     |  1  |  A  |  Q  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 0  0  1  0 |  2 |     |     |     |  2  |  B  |  R  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 0  0  1  1 |  3 |     |     |     |  3  |  C  |  S  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 0  1  0  0 |  4 |     |     |     |  4  |  D  |  T  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 0  1  0  1 |  5 |     |     |     |  5  |  E  |  U  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 0  1  1  0 |  6 |     |     |  &  |  6  |  F  |  V  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 0  1  1  1 |  7 |     |     |     |  7  |  G  |  W  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  0  0  0 |  8 |     |     |  (  |  8  |  H  |  X  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  0  0  1 |  9 |     |     |  )  |  9  |  I  |  Y  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  0  1  0 | 10 |     |     |     |     |  J  |  Z  |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  0  1  1 | 11 |     |     |     |     |  K  |     |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  1  0  0 | 12 |     |     |     |     |  L  |     |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  1  0  1 | 13 |     |     |  -  |     |  M  |     |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  1  1  0 | 14 |     |     |  .  |     |  N  |     |     |     |
   |------------+----|-----+-----+-----+-----+-----+-----+-----+-----|
   | 1  1  1  1 | 15 |     |     |  /  |     |  O  |     |     |     |
   o-----------------------------------------------------------------o

Acknowledgements ๐Ÿ™Œ

this whole document leans heavily on revision 1.3 of the ODETTE File Transfer Specification [OFTP] ๐Ÿ“š

so many people helped build this protocol, and their work deserves a shoutout ๐Ÿ‘‘. the extensions needed to use the Transmission Control Protocol were worked out and agreed on by the current members of ODETTE Working Group Four, who also gave super helpful reviews and comments on this doc ๐Ÿซถ

References ๐Ÿ“š

   [OFTP]  Organisation for Data Exchange by Tele Transmission in
   Europe, Odette File Transfer Protocol, Revision 1.3:1993

   [RFC-739]  Postel, J., Transmission Control Protocol, STD 7, RFC 739,
   September 1981

   [ISO-646] International Organisation for Standardisation, ISO
   Standard 646:1991, "Information technology -- ISO 7-bit coded
   character set for information interchange", 1991

   [ISO-6523] International Organisation for Standardisation, ISO
   Standard 6523:1984, "Data interchange -- Structures for the
   identification of organisations", 1984

   [ISO-8601] International Organisation for Standardisation, ISO
   Standard 8601:1988 "Data elements and interchange formats --
   Information interchange -- Representation of dates and times", 1988

   [NIFTP] High Level Protocol Group, "A Network Independent File
   Transfer Protocol", 1981

   [SNARK] Carroll, Lewis "The Hunting of the Snark", 1876

ODETTE Address ๐ŸŒท

the ODETTE File Transfer Protocol is a product of Working Group Four of the Organisation for Data Exchange by Tele Transmission in Europe. you can reach the working group through the ODETTE Secretariat ๐Ÿ’Œ

   ODETTE Secretariat
   Forbes House
   Halkin Street
   London
   SW1X 7DS
   United Kingdom

   Phone: +44 (0)171 344 9227
   Fax:   +44 (0)171 235 7112
   EMail  odette@odette.org
          keith.oxley@odette.org
          stephanie.bioux@odette.org

Author's Address โœ๏ธ

the author can be contacted at ๐Ÿ’–

   David Nash
   Ford Motor Company Limited
   Room 1/148, Central Office
   Eagle Way
   Warley
   Brentwood
   Essex
   CM13 3BW
   United Kingdom

   Phone: +44 (0)1277 253043
   EMail: dnash@ford.com
๐Ÿ“ฆ where this page comes from