anchor.diff:              Writers.setHeader "Content-Type" "application/octet-stream"
                   >=> Successful.ok (payload |> Payload.encodeToBinary |> Segment.toArray)
   
  -    let mainPart: WebPart = fun ctx -> async {
  -        let sid = idGenerator ()
  -        let handshake = {
  -            Sid = sid;
  -            Upgrades = config.Upgrades;
  -            PingTimeout = int config.PingTimeout.TotalMilliseconds;
  -            PingInterval = int config.PingInterval.TotalMilliseconds }
  -        let payload = Payload([Open(handshake)])
  +    let ll = Targets.create Debug [| "Bug" |]
  +    let createSocket socketId handleIncomming =
  +        let socket = {
  +            Id = socketId
  +            Transport = Polling
  +            IncomingMessages = MailboxProcessor<IncomingCommunication>.Start(fun inbox ->
  +                let rec loop (socket: Socket) = async {
  +                    let! msg = inbox.Receive()
  +                    match msg with
  +                    | NewMessage msg ->
  +                        ll.info (eventX (sprintf "Incoming %A" msg))
  +                        do! handleIncomming socket msg
  +                    | _ -> ()
  +                    return! loop socket
  +                }
  +
  +                let rec initLoop () = async {
  +                    let! msg = inbox.Receive()
  +                    match msg with
  +                    | IncomingCommunication.Init socket -> return! loop socket
  +                    | _ -> return! initLoop ()
  +                }
  +
  +                initLoop ()
  +                )
  +            OutgoingMessages = MailboxProcessor<OutgoingCommunication>.Start(fun inbox ->
  +                let rec loop (socket: Socket) messages (currentReplyChan: AsyncReplyChannel<Payload> option) = async {
  +                    let! msg = inbox.Receive()
  +                    match msg with
  +                    | AddMessage msg ->
  +                        match currentReplyChan with
  +                        | Some(chan) ->
  +                            ll.info (eventX (sprintf "%A AddMessage with reply channel, sending %A" socket.Id msg))
  +                            chan.Reply(Payload(msg::messages))
  +                            return! loop socket [] None
  +                        | None ->
  +                            ll.info (eventX (sprintf "%A AddMessage storing %A" socket.Id msg))
  +                            return! loop socket (msg::messages) None
  +                    | GetMessages rep ->
  +                        match messages, currentReplyChan with
  +                        | [], None->
  +                            ll.info (eventX (sprintf "%A GetMessages nothing yet" socket.Id))
  +                            return! loop socket [] (Some(rep))
  +                        | messages, None ->
  +                            ll.info (eventX (sprintf "%A GetMessages %i available" socket.Id messages.Length))
  +                            rep.Reply(Payload(messages))
  +                            return! loop socket [] None
  +                        | _, Some(_) ->
  +                            ll.error (eventX (sprintf "%A CROSS THE BEAMS" socket.Id))                            
  +                            failwith "Don't cross the beams !"
  +                    | _ ->
  +                        return! loop socket messages currentReplyChan
  +                }
  +
  +                let rec initLoop () = async {
  +                    let! msg = inbox.Receive()
  +                    match msg with
  +                    | OutgoingCommunication.Init socket -> return! loop socket [] None
  +                    | _ -> return! initLoop ()
  +                }
  +
  +                initLoop ()
  +            )
  +        }
  +
  +        socket.IncomingMessages.Post(IncomingCommunication.Init(socket))
  +        socket.OutgoingMessages.Post(OutgoingCommunication.Init(socket))
  +        socket
  +
  +    let getPart: WebPart = fun ctx -> async {
           let engineContext = EngineIoContext.FromHttp ctx
  -        let pipeline = setIoCookie config sid >=> respondPayload payload engineContext
  -        return! pipeline ctx
  +        match engineContext.SessionId with
  +        | None ->
  +            let socketId = idGenerator ()
  +            let handshake = {
  +                Sid = socketId;
  +                Upgrades = config.Upgrades;
  +                PingTimeout = int config.PingTimeout.TotalMilliseconds;
  +                PingInterval = int config.PingInterval.TotalMilliseconds }
  +
  +            let socket = createSocket (SocketId socketId) config.onPacket
  +            server.OpenSessions <- server.OpenSessions |> Map.add socket.Id socket
  +            
  +            ctx.runtime.logger.info (eventX (sprintf "Creating session with ID %s" socketId))
  +
  +            let payload = Payload([Open(handshake)])
  +
  +            let pipeline = setIoCookie config socketId >=> respondPayload payload engineContext
  +            return! pipeline ctx
  +        | Some(sessionId) ->
  +            let socketId = SocketId sessionId
  +            match server.OpenSessions |> Map.tryFind socketId with
  +            | Some(socket) ->
  +                let! payload = socket |> Socket.getOutgoing (30 * 1000)
  +                for message in payload |> Payload.getMessages do
  +                    ctx.runtime.logger.debug (eventX (sprintf "%s <- %A" sessionId message))
  +                let pipeline = setIoCookie config sessionId >=> respondPayload payload engineContext
  +                return! pipeline ctx
  +            | None ->
  +                return! RequestErrors.BAD_REQUEST "Unknown session" ctx
  +    }
  +
  +    let postPart: WebPart = fun ctx -> async {
  +        let engineContext = EngineIoContext.FromHttp ctx
  +        match engineContext.SessionId with
  +        | None -> return! RequestErrors.BAD_REQUEST "Unknown session" ctx
  +        | Some(sessionId) -> 
  +            let socketId = SocketId sessionId
  +            match server.OpenSessions |> Map.tryFind socketId with
  +            | Some(socket) ->
  +                let binary = engineContext.SupportsBinary
  +                let payload =
  +                    if binary then
  +                        ctx.request.rawForm |> Segment.ofArray |> Payload.decodeFromBinary
  +                    else
  +                        ctx.request.rawForm |> Text.Encoding.UTF8.GetString |> Payload.decodeFromString
  +                for message in payload |> Payload.getMessages do
  +                    ctx.runtime.logger.debug (eventX (sprintf "%s -> %A" sessionId message))
  +                    socket |> Socket.addIncoming message
  +                let pipeline = setIoCookie config sessionId >=> (Successful.ok [||])
  +                return! pipeline ctx
  +            | None ->
  +                return! RequestErrors.BAD_REQUEST "Unknown session" ctx
       }
           
       choose [
           Filters.pathStarts config.Path
  -            >=> mainPart
  +            >=>
  +            choose [
  +                Filters.GET >=> getPart
  +                Filters.POST >=> postPart
  +                RequestErrors.BAD_REQUEST "O_o"
  +            ]
               >=> cors config.CORSConfig
               >=> removeBuggyCorsHeader
               >=> disableXSSProtectionForIE
  
positive.code:     let conf = { EngineIoConfig.empty with Upgrades = Array.empty }
      let app =
          choose [
              serveEngineIo EngineIoConfig.empty
              Successful.OK "Hello World!"
          ]
      startWebServer defaultConfig app
      0
  
negative.code:         CookiePath: string option
          CookieHttpOnly: bool
          RandomNumberGenerator: RandomNumberGenerator
          onPacket: Socket -> PacketMessage -> Async<unit>
          getPacket: HttpContext -> Async<PacketMessage option>
          getPayload: HttpContext -> Async<Payload option>
      }
  
      with static member empty = {
              Path = "/engine.io/"
              CookieName = Some "io"
              CookiePath = Some "/"
              CookieHttpOnly = false
  