Posted to tcl by Stu at Wed Aug 22 23:32:54 GMT 2012view raw
- TIP:
- Title: Datagram I/O in Tcl
- Author: Alexandre Ferrieux, Colin McCormack
- Type: Project
- Tcl-Version: 8.7
- Created: 17-Aug-2012
- ~ Abstract
- This TIP adds support for Datagram I/O in Tcl (starting with UDP),
- with a pure event approach to packet reception (as opposed to
- hijacking the existing channel infrastructure).
- ~ Rationale
- UDP support is a long-awaited feature in Tcl. Some extensions have
- traditionally supported it through the channel abstraction. This is of
- course doable, but there is a nonnegligible cost in both complexity
- and performance due to the impedence mismatch between the "fluid"
- model behind channels and the "granular" world of packets or datagrams
- (where boundaries are significant). Another discrepancy is the
- existence of (per-packet) metadata (like the source address and port
- of an incoming UDP packet), which does not fit nicely in the
- (per-connection) options of the channel API (via fconfigure).
- Once this mismatch is acknowledged, it is easy to identify a better
- home for packet I/O in Tcl: let it be a direct event source (for the
- receive side), just like Tk or Snack.
- Indeed, hooking a callback for packet reception is a natural fit with
- Tcl's event-driven tradition, while preserving packet boundaries and
- easily exposing per-packet metadata.
- Sending is trivially handled by a direct per-packet call (but not
- disguised as a [puts]). Again, this naturally allows for boundary
- preservation and metadata specification.
- The script API put forth in this TIP is also designed for easy
- generalization to other kinds of packet I/O. Though only UDP is
- supported in the reference implementation, other protocols may be
- registered, and selected with the ''protocol'' paramater. Future
- additions may include:
- - raw IP sockets
- - USB
- - Bluetooth
- ~ Overall Specification
- The new '''dgram''' command creates a "datagram endpoint" of the given
- protocol:
- > '''dgram''' ''protocol'' ?''options''?
- Following the traditions of Tk and Snack, it returns a Tcl command,
- which takes subcommands implementing the needed verbs. An endpoint is
- thus created by:
- > set d ['''dgram''' ''protocol'' ?-''option'' ''value''? ...]
- The returned command lives by default in the ::tcl::dgram namespace;
- however, the generic ''-name'' option allows it to take a (possibly
- fully qualified) user-provided name:
- > dgram ''protocol'' -name foo ...
- creates (and returns) the command ::foo to hold the endpoint.
- Once created, its configuration can be tweaked by:
- > $d configure -''option'' ''value''
- and retrieved with
- > set value [$d configure -''option'']
- To close the endpoint, use:
- > $d close
- or, as in Tk, destroy the command:
- > rename $d {}
- or the whole namespace.
- Other verbs, and the detailed list of options, are
- protocol-specific. From now on, the specification concentrates on the
- UDP case. The rationale for *not* generalizing much is the feeling
- that the costs of parameter variability would largely outweigh the
- tiny amount of code sharing.
- ~ The UDP case
- With UDP, addresses and ports may only be specified on creation:
- > set d ['''dgram udp''' ?-localaddr ''address''? ?-localport ''port''?]
- They default to INADDR_ANY and 0, respectively. In case of port 0,
- after creation of the endpoint the actual port chosen by the OS can be
- retrieved with [$d configure]:
- > set d [dgram udp]
- > puts "Local port is: [$d configure -localport]"
- One can also specify remote address and port, meaning to connect() the
- underlying UDP socket:
- > set d ['''dgram udp''' ?-remoteaddr ''address'' -remoteport ''port''?]
- These options suffer no default, and must be simultaneously present or
- absent. The semantics, as is well known, is to tell the kernel (a) to
- forbid sending to any other destination, and (b) to discard all
- incoming packets sent by another source.
- All the other options may be specified on creation or through
- [configure].
- Sending is done with, unsurprisingly, the 'send' verb:
- > $d '''send''' ''payload'' ?''destaddr'' ''destport''?
- Its blocking semantics is that of the underlying protocol: it
- typically returns immediately, though the hardware may buffer the data
- for some time, and delivery is not guaranteed.
- The destination parameters can, unsurprisingly, be omitted if the
- endpoint has been created with the -remoteaddr/port options (connected
- mode).
- Receiving is done with the -listener callback:
- > $d '''configure -listener''' ''command_prefix''
- Subsequently, when an incoming packet hits Tcl in the event loop, the
- ''command_prefix'' is called with the endpoint identifier, payload and
- metadata:
- > ''command_prefix'' $d ''payload'' ''metadata_dict''
- where ''payload'' is the byte array of the UDP payload, and
- ''metadata_dict'' is a dict containing at least three options:
- > '''-remoteaddr''' ''address''
- > '''-remoteport''' ''port''
- > '''-localaddr''' ''address''
- When ''command_prefix'' is the empty string, the notifier gives up
- interest in the underlying UDP socket; this allows to keep the port
- bound while letting the OS buffer any incoming packets (up to a
- configurable limit) without any script-level handling, while leaving
- the event loop active. This is similar to setting a fileevent to {}.
- ~ Advanced UDP options
- (TODO: multicast, ttl, buffersize ...)
- ~ Copyright
- This document has been placed in the public domain.