1 July 1996
22 January 2002
14 August 2011


      This is a discussion of the architecture of flow. The primary classes are those of the Correspondent hierarchy:

   Correspondent
      Client
         IncomingClient
            IncomingHTTPClient
            IncomingIdentificationClient
            IncomingMIDIClient
            IncomingVISCAClient
            IncomingX10Client
            IncomingTelnetClient
         OutgoingClient
            OutgoingHTTPClient
            OutgoingIdentificationClient
            OutgoingIRCClient
            OutgoingMIDIClient
            OutgoingNNTPClient
            OutgoingPOPClient
            OutgoingSMTPClient
            OutgoingTimeClient
            OutgoingVISCAClient
            OutgoingX10Client
      Server

      These classes do the recurring bookkeeping involved in writing clients and servers. For example, a Server keeps track of the clients connected to it, and has simple default behavior for servicing and disconnecting them. Transport details are encapsulated by NetStreams (described below). Correspondent authors can focus on protocol details, with a streamy message interface, instead of transport details.

      When both client and server systems are using Flow, an OutgoingClient uses its stream to connect to a Server, then communicates with a remote IncomingClient that the Server creates for the conversation. Likewise, the IncomingClient uses its stream, created by the Server, to communicate with the remote OutgoingClient. The Server uses its stream only to listen for connection requests from remote OutgoingClients, and to create IncomingClients for servicing them.

      With this arrangement one can model the different sides of a conversation independently, including protocols with many-way interactions.

      Of course, when a participant system is not using Flow, the required behavior is provided by some other piece of software. For example, in the hierarchy above, "OutgoingTelnetClient" isn't listed because I have no need to make my own outgoing telnet client; I just use the one that comes with the host operating system. I did implement IncomingTelnetClient, because it's part of customized telnet behavior I wanted for Quoth, another project of mine. In fact, it was that project which pointed out the need to model incoming and outgoing client behavior separately.

      It's straightforward to combine multiple correspondents in an "application". For example, a mailer would probably use multiple OutgoingPOPClients and OutgoingSMTPClients.

      I rewrote the Stream hierarchy:

   Stream
      PositionableStream
         WritableStream
            DiscardingStream
            ExternalStream
               FileStream
                  AppendingFileStream
                  AppendingFileStreamWriter
                  RemoteFileStream
               NetStream
                  Conversation (used for speech recognition/synthesis)
                  HardwareStream
                     1394Stream
                     AudioStream
                     MIDIStream
                     ParallelPortStream
                     SerialPortStream
                  SocketStream
                     TCPStream
                     UDPStream
            NetMessage
               HTTPMessage
                  HTTPMethod
                     GET
                     LOCK
                     MOVE
                     OPTIONS
                     PROPFIND
                     PROPPATCH
                     PUT
               MailMessage
                  NewsMessage
            RingBuffer
               InfiniteRingBuffer
            TextStream
         RandomNumberStream

      I was originally motivated by the need to get a filesystem working on custom hardware. The Squeak filesystem support at the time (including the Stream hierarchy) was cumbersome, with a lot of unreachable and redundant code and an overly-complicated class factoring. The new factoring is much simpler, unifies all "external" resources with the ExternalStream hierarchy, and has smarter buffering.

      The NetMessage hierarchy extends stream protocol to the creation of HTTP, mail, and news messages, minimizing copying.

      External resources are named by Universal Resource Locators (URLs):

   UniformResourceLocator
      AuthenticatingLocator
      HierarchicalLocator
         FileLocator
         Filename
         HypertextLocator
         MIDILocator
      TelnetSession
   MailAddress
   MessageLocator
      MailMessageLocator
      NewsMessageLocator

All low-level access to the outside world is factored into one hierarchy:

   ExternalResource
      File
      MakeControllerKit (with OSC support defined separately)
      Peer
         HardwarePort
            AudioPort
            IEEE1394Port
            InfraredPort
            MIDIPort
            ParallelPort
            SerialPort
            USBPort
         Socket
            TCPSocket
               ClientTCPSocket
                  IncomingClientTCPSocket
                  OutgoingClientTCPSocket
               ServerTCPSocket
            UDPSocket
      PhidgetInterfaceKit
      SocketAddressResolver
      SpeechRelay

     

      Each ExternalResource has a "handle" instance variable, an opaque identifier which is known to the virtual machine (there is no need to model resource handles separately at the object level). All external resources support an interface which makes them suitable for use as collections for NetStreams. File will probably have subclasses to account for host platform differences.

      Exception handling is used in many places by the classes above, usually for "ensured behavior". For example, one may open a file stream and write to it, ensuring that the file will be closed despite interruptions.