                       (log/error ex "This really shouldn't pass")
                       (is (not ex))))
                   nil))]
+        (log/info prelog
+                  incoming
+                  "triggered a response:"
+                  next-message)
         ;; Hmm...I've wound up with a circular dependency
         ;; on the io-handle again.
         ;; Q: Is this a problem with my architecture, or just
         ;; a testing artifact?
         (when next-message
+          (swap! client-state update ::count inc)
           (buffer-response! @client-atom
                             prelog
                             next-message
                             "Buffered bytes from child"
-                            "Giving up on sending message from child"))))))
+                            "Giving up on sending message from child"
+                            {}))))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-;;; Tests functions
+;;; Tests
 
 (deftest handshake
   (let [prelog (utils/pre-log "Handshake test")]

   success-message
   error-message
   error-details]
  ;; This actually sends a stream of data.
  ;; So prepend with the byte count
  (let [printed (pr-str response)
        payload (.getBytes printed)
        response-length (count payload)
        ;; 2 bytes for length encoding
        buffer (+ 2 response-length)]
    (b-t/uint16-pack! buffer 0 response-length)
    (b-t/byte-copy! buffer 2 response-length payload)
    (m-t/try-multiple-sends message/child->!
                            prelog
                            5
                            io-handle
                            buffer
                            success-message
                            error-message
                            error-details)))

(s/def ::prefix (s/nilable bytes?))
(s/def ::count nat-int?)
(s/def ::state (s/keys :req [::count
                             ::prefix]))
(s/def ::next-object any?)
(s/fdef extract-next-object-from-stream
        :args (s/cat :state ::state
                     :bs bytes?)

            [frereth-cp.message.specs :as specs]
            [frereth-cp.shared.bit-twiddling :as b-t]
            [frereth-cp.util :as utils]
            [gloss.core :as gloss]
            [gloss.io :as io]
            [manifold.deferred :as dfrd]
            [manifold.stream :as strm])
  (:import io.netty.buffer.Unpooled))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Specs

(s/def ::prefix (s/nilable bytes?))
(s/def ::count nat-int?)
(s/def ::state (s/keys :req [::count
                             ::prefix]))
(s/def ::next-object any?)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Magic constants

(def protocol
  (gloss/compile-frame
   (gloss/finite-frame :uint16
                       (gloss/string :utf-8))
   pr-str
   edn/read-string))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Helper functions

(defn consumer
  [io-handle prelog time-out succeeded? bs]
  ;; Note that, at this point, we're blocking the
  ;; I/O loop.
  ;; Whatever happens here must return control
  ;; quickly.
  (log/info prelog "Message over network")
  ;; Checking for the server state is wasteful here.
  ;; And very dubious...depending on implementation details,
  ;; it wouldn't take much to shift this over to triggering
  ;; a deadlock (since we're really running on the event loop
  ;; thread).
  ;; Actually, I'm a little surprised that this works at all.
  ;; And it definitely *has* had issues.
  ;; Q: But is it worth it for the test's sake?
  (let [state (message/get-state io-handle time-out ::timed-out)]
    (if (or (= ::timed-out state)
            (instance? Throwable state)
            (nil? state))
      (let [problem (if (instance? Throwable state)
                      state
                      (ex-info "Non-exception"
                               {::problem state}))]
        (log/error problem prelog "Failed!")
        (dfrd/error! succeeded? problem))
      (message/parent->! io-handle (io/encode protocol bs)))))

(defn srvr->client-consumer
  "This processes bytes that are headed from the server to the client"
  [client-io time-out succeeded? bs]
  (let [prelog (utils/pre-log "server->client consumer")]
    (consumer client-io prelog time-out succeeded? bs)))

(defn client->srvr-consumer
  [server-io time-out succeeded? bs]
  (let [prelog (utils/pre-log "server->client consumer")]
    (consumer server-io prelog time-out succeeded? bs)))

(defn buffer-response!
  [io-handle
