TLS package server interface do not seem to allow for asyncrhonious communication

Hi Haskeleers, I got a working SSL server using the TLS package. Great. However, I really intended to use SSL for an asynchronous server. That is, the server must constantly listen for a client message, which may result in zero or more messages send _to_ the client. And the server will, without being waken up by a client message, send messages to the client. And this interface http://hackage.haskell.org/packages/archive/tls/0.3.1/doc/html/Network-TLS-S... do not seem to allow for an asynchronous server. That is, whenever I call: recvPacket :: Handle -> TLSServer IO (Either TLSError [Packet]) or recvData :: Handle -> TLSServer IO ByteString The server is stuck until the client sends a message. Or am I missing something? Contrast this to Network package socket implementation. Here I can spawn two threads and simultaneously listen for client messages and send messages to the client. It seems to me that a general SSL implementation should not preclude asynchronous servers. I know, the TLS package is not more than a few months old and one can already use it for SSL servers and clients, which is quite impressive. So do not read this as a negative comment, more as suggestions for a better interface. Regards, Mads Lindstrøm

Maybe I'm missing something - but shouldn't the code listening on the
Handle already be in it's own thread?
The general recipe is:
1. Bind a socket to port
2. Call Network.accept, then take the resultant Handle, call forkIO
with the TLS actions and the resultant handle. Go back to 1.
So even though the TLS code blocks on the handle, that's in a
different thread from the code which is waiting on the socket to
accept additional connections.
Take care,
Antoine
On Tue, Dec 14, 2010 at 2:21 PM, Mads Lindstrøm
Hi Haskeleers,
I got a working SSL server using the TLS package. Great. However, I really intended to use SSL for an asynchronous server. That is, the server must constantly listen for a client message, which may result in zero or more messages send _to_ the client. And the server will, without being waken up by a client message, send messages to the client.
And this interface http://hackage.haskell.org/packages/archive/tls/0.3.1/doc/html/Network-TLS-S... do not seem to allow for an asynchronous server. That is, whenever I call:
recvPacket :: Handle -> TLSServer IO (Either TLSError [Packet])
or
recvData :: Handle -> TLSServer IO ByteString
The server is stuck until the client sends a message. Or am I missing something?
Contrast this to Network package socket implementation. Here I can spawn two threads and simultaneously listen for client messages and send messages to the client.
It seems to me that a general SSL implementation should not preclude asynchronous servers. I know, the TLS package is not more than a few months old and one can already use it for SSL servers and clients, which is quite impressive. So do not read this as a negative comment, more as suggestions for a better interface.
Regards,
Mads Lindstrøm
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Wed, Dec 15, 2010 at 12:20 AM, Antoine Latter
Maybe I'm missing something - but shouldn't the code listening on the Handle already be in it's own thread?
The general recipe is:
1. Bind a socket to port 2. Call Network.accept, then take the resultant Handle, call forkIO with the TLS actions and the resultant handle. Go back to 1.
Yes, for 99% of users this is the right thing to do. Note that Haskell
threads are lightweight green threads and that under the hood you are
getting efficient async networking using epoll() or kqueue() on
Linux/OSX.
G
--
Gregory Collins

Hi Antoine, Rereading my earlier post, I can see I did not explain myself properly. What I do now with sockets is: 1. Bind a socket to a port 2. Call Network.accept, then take the resultant Handle, and call forkIO _twice_ with the handle. Making one thread that listens for incoming messages and one thread that sends outgoing messages. And then I go back to one. That is, two threads for each handle. I follow the scheme above, as my server do not follow a request/response pattern, but is asynchronous and must never get blocked by a client that do not send messages. Why do I not think, I cannot do the same thing with the TLS package? Because of this API description: "recvData :: Handle -> TLSServer IO ByteStringSource recvData get data out of Data packet, and automatically renegociate if - a Handshake ClientHello is received" Thus, recvData will not only read messages from the handle, it may also do a handshake. I presume that a handshake will both send and receive data. Thus, I would have thread that just sends data, and another thread that both sends and receives data. I am afraid that the two threads may "step on each others toes". With ordinary sockets, I have one thread that only sends data, and another thread that only receives data. So with ordinary sockets there is no chance of "stepping on each others toes". Also the TLSServer monad contains state. If I start two threads using the same SSL connection, I presume that the TLSServer-state will be different for the two threads. And I presume that two threads using the same SSL connection, needs the same state in the TLSServer monad. One workaround is use two SSL connections for each client, but I would like to avoid that. Regards and hope I make myself clearer, Mads On Tue, 2010-12-14 at 17:20 -0600, Antoine Latter wrote:
Maybe I'm missing something - but shouldn't the code listening on the Handle already be in it's own thread?
The general recipe is:
1. Bind a socket to port 2. Call Network.accept, then take the resultant Handle, call forkIO with the TLS actions and the resultant handle. Go back to 1.
So even though the TLS code blocks on the handle, that's in a different thread from the code which is waiting on the socket to accept additional connections.
Take care, Antoine
On Tue, Dec 14, 2010 at 2:21 PM, Mads Lindstrøm
wrote: Hi Haskeleers,
I got a working SSL server using the TLS package. Great. However, I really intended to use SSL for an asynchronous server. That is, the server must constantly listen for a client message, which may result in zero or more messages send _to_ the client. And the server will, without being waken up by a client message, send messages to the client.
And this interface http://hackage.haskell.org/packages/archive/tls/0.3.1/doc/html/Network-TLS-S... do not seem to allow for an asynchronous server. That is, whenever I call:
recvPacket :: Handle -> TLSServer IO (Either TLSError [Packet])
or
recvData :: Handle -> TLSServer IO ByteString
The server is stuck until the client sends a message. Or am I missing something?
Contrast this to Network package socket implementation. Here I can spawn two threads and simultaneously listen for client messages and send messages to the client.
It seems to me that a general SSL implementation should not preclude asynchronous servers. I know, the TLS package is not more than a few months old and one can already use it for SSL servers and clients, which is quite impressive. So do not read this as a negative comment, more as suggestions for a better interface.
Regards,
Mads Lindstrøm
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Thu, Dec 16, 2010 at 2:38 PM, Mads Lindstrøm
Hi Antoine,
Rereading my earlier post, I can see I did not explain myself properly. What I do now with sockets is:
1. Bind a socket to a port
2. Call Network.accept, then take the resultant Handle, and call forkIO _twice_ with the handle. Making one thread that listens for incoming messages and one thread that sends outgoing messages. And then I go back to one. That is, two threads for each handle.
I follow the scheme above, as my server do not follow a request/response pattern, but is asynchronous and must never get blocked by a client that do not send messages.
Ah, I see. I'm not sure how a different interface would help you here - you would still have the problem of not being able to send on the socket until after the Handshake finished. Maybe a better interface would be along the lines of: -- | Do not use the handle when you are done! openTLSConnection: Handle -> { information? Maybe not needed} -> IO TLSConnection And then some thread-safe operations on the TLSConnection: recv :: TLSConnection -> Int -> IO ByteString send :: TLSConnection -> ByteString -> IO () But I don't know much about either TLS nor the existing TLS library, so there might be some very good reasons that this won't work. Antoine
Why do I not think, I cannot do the same thing with the TLS package? Because of this API description:
"recvData :: Handle -> TLSServer IO ByteStringSource
recvData get data out of Data packet, and automatically renegociate if - a Handshake ClientHello is received"
Thus, recvData will not only read messages from the handle, it may also do a handshake. I presume that a handshake will both send and receive data. Thus, I would have thread that just sends data, and another thread that both sends and receives data. I am afraid that the two threads may "step on each others toes". With ordinary sockets, I have one thread that only sends data, and another thread that only receives data. So with ordinary sockets there is no chance of "stepping on each others toes".
Also the TLSServer monad contains state. If I start two threads using the same SSL connection, I presume that the TLSServer-state will be different for the two threads. And I presume that two threads using the same SSL connection, needs the same state in the TLSServer monad.
One workaround is use two SSL connections for each client, but I would like to avoid that.
Regards and hope I make myself clearer,
Mads
On Tue, 2010-12-14 at 17:20 -0600, Antoine Latter wrote:
Maybe I'm missing something - but shouldn't the code listening on the Handle already be in it's own thread?
The general recipe is:
1. Bind a socket to port 2. Call Network.accept, then take the resultant Handle, call forkIO with the TLS actions and the resultant handle. Go back to 1.
So even though the TLS code blocks on the handle, that's in a different thread from the code which is waiting on the socket to accept additional connections.
Take care, Antoine
On Tue, Dec 14, 2010 at 2:21 PM, Mads Lindstrøm
wrote: Hi Haskeleers,
I got a working SSL server using the TLS package. Great. However, I really intended to use SSL for an asynchronous server. That is, the server must constantly listen for a client message, which may result in zero or more messages send _to_ the client. And the server will, without being waken up by a client message, send messages to the client.
And this interface http://hackage.haskell.org/packages/archive/tls/0.3.1/doc/html/Network-TLS-S... do not seem to allow for an asynchronous server. That is, whenever I call:
recvPacket :: Handle -> TLSServer IO (Either TLSError [Packet])
or
recvData :: Handle -> TLSServer IO ByteString
The server is stuck until the client sends a message. Or am I missing something?
Contrast this to Network package socket implementation. Here I can spawn two threads and simultaneously listen for client messages and send messages to the client.
It seems to me that a general SSL implementation should not preclude asynchronous servers. I know, the TLS package is not more than a few months old and one can already use it for SSL servers and clients, which is quite impressive. So do not read this as a negative comment, more as suggestions for a better interface.
Regards,
Mads Lindstrøm
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Antoine
On Thu, Dec 16, 2010 at 2:38 PM, Mads Lindstrøm Maybe a better interface would be along the lines of:
-- | Do not use the handle when you are done! openTLSConnection: Handle -> { information? Maybe not needed} -> IO TLSConnection
And then some thread-safe operations on the TLSConnection:
recv :: TLSConnection -> Int -> IO ByteString send :: TLSConnection -> ByteString -> IO ()
Or it could be: openTLSConnection: Handle -> { Certificates & private key} -> IO Handle the returned handle would then act like a normal handle, except that it would encrypt and decrypt data. But I do not know if it is possible to implement that. /Mads

On Tue, Dec 14, 2010 at 09:21:48PM +0100, Mads Lindstrøm wrote:
Hi Haskeleers,
[snip] It seems to me that a general SSL implementation should not preclude asynchronous servers. I know, the TLS package is not more than a few months old and one can already use it for SSL servers and clients, which is quite impressive. So do not read this as a negative comment, more as suggestions for a better interface.
Hi Mads, You're right about the interface; but as Antoine pointed out, for now you can just use a thread for each connection. I do hope to at some point have a more rich interface for IO; I'm definitely looking to adopt Michael's TLS enumerator client interface (see the excellent http-enumerator package), but for the server I haven't really though about it yet. -- Vincent
participants (4)
-
Antoine Latter
-
Gregory Collins
-
Mads Lindstrøm
-
Vincent Hanquez