 
     var delegate : WSConnectionDelegate?
     private var frameReader: WSFrameReader
-    private var messageReader : WSMessageReader
     private var frameWriter: WSFrameWriter
-    private var messageWriter : WSMessageWriter
 
     public var onMessage : MessageCallback?
     public var onClosed : ClosedCallback?
     private var controlFrameBuffer : ReadBufferType = ReadBufferType.alloc(256)
-
+    
+    public var transportClosed = false
+    
     public init(_ reader: Reader, writer: Writer, _ extensions: [WSExtension])
     {
+        self.maxFrameWriteSize = DEFAULT_MAX_FRAME_SIZE
         self.frameReader = WSFrameReader(reader)
-        self.messageReader = WSMessageReader(frameReader)
         self.frameWriter = WSFrameWriter(writer)
-        self.messageWriter = WSMessageWriter(frameWriter)
-
-        messageReader.onControlFrame = self.handleControlFrame
-        messageReader.onClosed = {
-            self.connectionClosed()
-        }
-        messageReader.onMessage = {(message) in
-            self.onMessage?(message: message)
-        }
-        messageWriter.onClosed = {
-            self.connectionClosed()
-        }
-
-        start()
+
+        startReading()
         // So at this point we have a frame reader from which *something* can 
         // consume frames.  So messages (and channels) are a higher level 
         // abstraction on top of frames.  We have a message object from which

    }
}

public class WSMessageWriter
{
    public typealias ClosedCallback = Void -> Void
    public var transportClosed = false
    public var onClosed : ClosedCallback?
    
    /**
     * Frames wont be bigger than this
     */
    private var maxFrameSize : Int = DEFAULT_MAX_FRAME_SIZE
    
    private var currMessageCount = 0
    private var allMessages = [WSMessage]()
    private var currentMessage : WSMessage?
    
    private var writer : WSFrameWriter
    
    public init(_ writer: WSFrameWriter, maxFrameSize: Int)
    {
        self.maxFrameSize = maxFrameSize
        self.writer = writer
    }
    
    public convenience init(_ writer: WSFrameWriter)
    {
        self.init(writer, maxFrameSize: DEFAULT_MAX_FRAME_SIZE)
    }
    
    
    /**
     * Starts a new message that can be streamed out by the caller.
     * Once a message is created it can be written to continuosly.
     */
    public func startMessage(opcode: WSFrame.Opcode) -> WSMessage
    {
        currMessageCount += 1
        let newMessage = WSMessage(type: opcode, id: String(format: "msg:%05d", currMessageCount))
        allMessages.append(newMessage)
        return newMessage
    }
    
    /**
     * Appends more data to a message.
     */
    public func write(message: WSMessage, maskingKey: UInt32, source: Payload, isFinal: Bool, callback: CompletionCallback?)
    {
        // queue the request
        if self.transportClosed
        {
            callback?(error: IOErrorType.Closed)
        } else {
            message.write(source, isFinal: isFinal, maskingKey: maskingKey, callback: callback)
            continueWriting()
        }
    }
    
    /**
     * Closes the message.  This message can no longer be written to.
     */
    public func closeMessage(message: WSMessage, callback: CompletionCallback?)
    {
        if self.transportClosed
        {
            callback?(error: IOErrorType.Closed)
        } else {
            message.close(callback)
        }
    }
    
    /**
     * Writing messages is slightly simpler than reading messages.  With reading there was the problem of not
     * knowing when a message started and having to notify connection handlers on new messages so that *then*
     * they could initiate reads.
     *
     * With writes this problem does not exist.  ie a write can only be initiate by the connection handler and
     * each write marks the start of a new message.  How the message gets fragment is what this writer controls
     * in concert with the actual message source that is provided at the start of a write.
     *
     * So to prevent a front of line blocking of messages, round-robin (or with some other custom scheduling
     * technique) can be used to decide which message is to be sent in each write call.
     */
    private func continueWriting()
    {
        // only start a request if the writer is idle
        // (if it is already writing a frame then dont bother it)
        if writer.isIdle
        {
            if currentMessage != nil
            {
                sendNextFrame(currentMessage!)
            } else {
                // pick a message which has messages
                for message in allMessages
                {
                    if !message.writeQueue.isEmpty
                    {
                        currentMessage = message
                        continueWriting()
                        return
                    }
                }
            }
        }
    }
    
    private func sendNextFrame(message: WSMessage)
    {
        message.writeNextFrame(writer, maxFrameSize: maxFrameSize) { (writeRequest, error) -> Void in
            if error != nil
            {
                self.transportClosed = (error as? IOErrorType) == IOErrorType.Closed
                writeRequest?.callback?(error: error)
                self.unwindWithError(message, error: error!)
            }
            else
            {
                if !message.hasMoreFrames
                {
                    self.currentMessage = nil
                    assert(self.writer.isIdle)
                }
                writeRequest?.callback?(error: error)
                self.continueWriting()
            }
        }
    }
    
    /**
     * Called when a read error occurred so all queued requests now need to be cancelled
     * with the error.
     */
    private func unwindWithError(message: WSMessage, error: ErrorType)
    {
        Log.debug("Unwinding with error: \(error)")
        while let next = message.writeQueue.first
        {
            message.writeQueue.removeFirst()
            next.callback?(error: error)
        }
    }
}

                // close the connection
                self.readerClosed()
            } else if frame.opcode == WSFrame.Opcode.ContinuationFrame {
                if currentReadMessage == nil
                {
                    self.readerClosed()
                } else {
                    callback?(error: nil)
                }
            } else {
                if currentReadMessage != nil
                {
                    // we already have a message so drop this
                    self.readerClosed()
