WUMP: Windowing UDP Message Protocols
    My UDP Message Protocol comes in three flavors: BUMP, HUMP, and CHUMP.
        BUMP:  Basic UDP Message Protocol
        HUMP:  Handoff UDP Message Protocol
        CHUMP: Cookie-handling UDP Message Protocol
    As a group, these are known as WUMP: Windowing UDP Message Protocol. These
    are three related protocols for requesting and downloading a file from a
    server. HUMP and CHUMP are basically theoretical attempts to resolve obscure
    technical issues; the practical protocol for implementation is BUMP, and
    WUMP without further clarification usually refers to BUMP. All three support
    sliding windows, although a windowsize of 1 is supported if the client
    requests it.
    
    Every packet begins with two bytes for PROTOCOL and OPCODE. PROTOCOL is 1,
    2, or 3 respectively for BUMP, HUMP, or CHUMP; OPCODEs are
    
    
      
        
          | REQ 
 | 1 
 | 
        
          | DATA 
 | 2 
 | 
        
          | ACK 
 | 3 
 | 
        
          | ERROR/CANCEL 
 | 4 
 | 
        
          | HANDOFF 
 | 5 (HUMP only) 
 | 
      
    
    
    These will generally be defined in an include/import file.
    
    Each protocol begins with the client sending a REQ packet to the server, at
    port SERVERPORT. As detailed below, the REQ packet contains both filename
    and window size.  Check the current header/import files for the numeric
    value of SERVERPORT.
    
    The server will not transfer the
    file from SERVERPORT; the problem is that if multiple simultaneous transfers
    are in progress then the server would have a considerable amount of
    bookkeeping to do.  Instead, the server will create a child process and
    will "hand off" the transfer to that process, which will send the data from
    some new port CHILDPORT. The main difference between the three protocols
    here is in how this handoff is accomplished. The client never changes its
    port number; each separate client instance has a (hopefully) new, unique
    port, and so there is no conflict.
    
    The third protocol, CHUMP, contains a "cookie" sent by the client in
      its initial REQ and echoed back by the server in every subsequent packet.
      The cookie fields don't appear at all in the other protocols. The CHUMP
      here is more properly CHUMP8, in that it sends an 8-byte cookie; if 4-byte
      cookies were desired then a new protocol CHUMP4 would be defined to
      support that packet layout. CHUMP16, with 16-byte cookies, would be
      another possibility. By not making the cookie size variable, and specified
      in the request packet, we ensure that DATA always begins at the same
      offset for a given protocol. We use COOKIESIZE below as if it were a
      constant, nominally 8; separate packet layouts would have to be defined
      for other sizes.
    
    
    Packet layouts
    REQ packets:
    
           
    protocol        1 byte
           
    opcode          1 byte
           
    winsize         2 bytes: size of
    offered receive window
               
    cookie      COOKIESIZE bytes, CHUMP only!
           
    filename        N bytes (stored with NUL
    below as a C string)
            NUL
    byte        1 byte
    
    DATA packets will hold a 4-byte sequence number, and 512 bytes of data:
           
    protocol        1 byte
           
    opcode          1 byte
           
    pad               
2
    bytes; used for alignment only.
           
    blocknum        4 bytes
               
    cookie      COOKIESIZE bytes; CHUMP only!
           
    data           
    DATASIZE bytes, or less, up to length of packet
    
    ACK packets are like DATA, but with no data field:
           
    protocol        1 byte
           
    opcode          1 byte
           
    pad               
2
    bytes; used for alignment only.
           
    blocknum      4 bytes
               
    cookie      COOKIESIZE bytes; CHUMP only!
    
    ERROR packets support error and status reporting and cancellation.
           
    protocol        1 byte
           
    opcode          1 byte
           
    errorcode       2 bytes
           
    cookie      COOKIESIZE bytes; CHUMP only!
    
    HANDOFF packets are used by the server in reporting to the client the new
    port
    it will use. Note that a HANDOFF packet, like any other, may be lost.
           
    protocol        1 byte
           
    opcode          1 byte
           
    newport         2 bytes
    
    
    BUMP: Basic UDP Message Protocol
    Client sends REQ to SERVERPORT. Server responds from CHILDPORT with the
    first windowful of data. Client first learns of the new CHILDPORT when this
    windowful of data arrives; note that the client should be prepared to "latch
    on" to CHILDPORT if it sees any of
    the data in the first window.
    
             
    client            
                       
    server
             
      |               
                     |
               
      |             
                    
        |
                |   
      --REQ-to-SERVERPORT-->     |
               
      |               
 
                   |
                |
          <-DATA-from-CHILDPORT--   |
               
      |                   
                 |
    
    PROBLEMS: 
    
    When the client sees data coming in from CHILDPORT, it has no explicit
    assurance that this data is actually in response to the REQ. The "handoff"
    is unauthenticated, so to speak.
    
    If the client sends two REQs, then the server will start up two CHILDPORTs.
    Whichever is the first to get data to the client will be the port chosen for
    the transfer; the protocol will need a mechanism for cancelling the transfer
    on the other port. The simplest such protocol is for the client to send a
    CANCEL message to any port from which it receives data, other than the port
    it initially "latches on" to.
    
    
    HUMP: Handoff UDP Message Protocol
    Client sends REQ to SERVERPORT. Server sets up CHILDPORT, and then
    sends a HANDOFF packet from SERVERPORT which contains the new CHILDPORT.
    The client then sends an ACK[0] to this CHILDPORT to start the data.
    
    The advantage is that the client receives clear instructions as to 
    where the data is to come from.
    
           
    client                 
                   server
             
|                           
      |
                |
      -----REQ-to-SERVERPORT-->  |
               
      |                           
      |
                |
      <-HANDOFF-from-SERVERPORT- |
               
      |                           
      |
                |
      --ACK[0]-to-CHILDPORT-->   |
               
      |                           
      |
                |
      <--DATA-from-CHILDPORT---  |
               
      |                           
      |
    
    PROBLEMS:
    
    If the HANDOFF is lost, the CHILDPORT waits forever. The server will need to
    be sure it times out promptly. When the REQ is eventually resent, then the
    server will create a new child process and CHILDPORT to handle
    what it sees as a new request.
    
    The HANDOFF is not to be
    retransmitted on timeout. If it were, then if the REQ were retransmitted
    we'd again be in the situation with two separate child processes on two
    separate CHILDPORTs sending HANDOFFs, and the client would have to accept
    the first and CANCEL the second as in BUMP.
    
    Note that if the REQ is lost the server never sees anything and so never
    creates any child processes.
    
    
    CHUMP: Cookie-Handling UDP Message Protocol
    
    Client sends a REQ to SERVERPORT. The REQ contains a "cookie"; some long
    hash of, say, the filename+timestamp. The server includes this cookie in
    each DATA packet. We now follow the strategy of BUMP; *however* the presence
    of the cookie makes it clear that the incoming DATA from CHILDPORT is
    coming as a direct result of the REQ sent to the SERVERPORT.
    
    PROBLEMS:
    
    The cookie consumes bandwidth. A 32-bit cookie doesn't consume too much,
    although 64 bits might be safer.
    
    If someone eavesdrops on the unencrypted cookie, malicious attacks are still
    possible.
    
    Note also that the server has no way to protect the client from chaos, if
    the client always chooses the same cookie.
    
    
    Final packets
    
    All three protocols will use the sliding-window protocol to send data. The
    end of the file will be marked by a packet with number of data bytes less
    than 512 (the number of data bytes may be zero, but the UDP portion of the
    packet will not have size zero due to the header.) This strategy comes from
    TFTP.
    
    Lost-final-ACK problem
    
    Note that if the client sends the final ACK and exits, and this ACK is lost,
    then the server will continue to retransmit the final DATA. 
    
    The usual solution is to have the client send the final ACK and then
    "linger", or "dally", continuing to listen for duplicate DATA. The client at
    this point is only prepared to retransmit the ACK; it has already received
    all the data. For this reason, and because the linger period should be
    several timeout intervals (eg 10 seconds), lingering is best done in the
    background.
    
    Old-late-duplicates problem
    
    Suppose we transfer data via one of the above; the client uses CPORT and the
    server uses CHILDPORT. During the transfer, an extra DATA[2] is generated.
    Then, we transfer another file,
    and happen to choose the same ports at both ends. Choosing the same ports
    makes it arguably the same "connection", so we'll call it a second incarnation
    of the connection. During this second transfer, at the point we're expecting
    DATA[2], we get the old late DATA[2] from the first
    incarnation of the connection!
    
    Oops.
    
    Solutions:
    
    We can make sure at least one endpoint chooses a new port number each time.
    This is another justification for the use of the server CHILDPORT; this is a
    port choice under the server's control.
    
    Note that CHUMP has some additional protection here: packets with the wrong
    cookie are presumably from an old incarnation of the connection, and can be
    ignored. It is the client's responsibility to choose non-duplicate cookies,
    but then the client is the one who receives all the data (that is, data does
    not flow bidirectionally), so this isn't necessarily inappropriate.