Ocaml-ssl, Unix.select and zero return

I’m using SSL for reading data from various remote services over secure websockets. The scheme is following: I create the socket, embed it in the SSL context and add the socket to the reading list for Unix.select. When the socket fires, I use Ssl.read to get the data.

Everything is working well except with the one service where I get Ssl.Read_error.Error_syscall: error:00000000:lib(0):func(0):reason(0) after receiving each websocket frame (size ~5-6Kb). By the way, frames here are much bigger than on other services, but I’m not sure it’s the reason.

I ignore syscall errors, and most probably loose some data, because frames continue to arrive. Then, always after one minute I get Ssl.Read_error.Error_zero_return: error:00000000:lib(0):func(0):reason(0), which means the peer closed SSL socket for writing and I have to restart the process because no new data will be received from this socket.

Problem is perfectly reproducible. At the same time examples for this service and my own test implementation with Node.JS receive the data for hours without any problems.

I assume I do something wrong or setup socket/SSL too straightforward (see below).

Any help or ideas would be strongly appreciated.

let sock = Unix.socket PF_INET SOCK_STREAM 0 in
let laddr = Unix.inet_addr_of_string p.interface in
Unix.bind sock (ADDR_INET (laddr,0));
Unix.connect sock addr;
let (sock, res) =
let req = Bytes.of_string http_request in
if ssl then begin
Ssl.init ();
let ctx = create_context TLSv1_2 Client_context in
let sock = Ssl.embed_socket sock ctx in
Ssl.connect sock;
(SslSock sock, (write sock req 0 http_request_len))
end else
(UnixSock sock, (Unix.write sock req 0 http_request_len))

If the problem is reproducible then capture a packet trace with Wireshark, and see if you can spot why it went wrong. Even without decrypting the packets you should be able to see handshake phases and encrypted tls alerts (usually close_notify). If you run the server you can provide wireshark with the private keys and then it should also be able to decrypt traffic, see https://sharkfesteurope.wireshark.org/assets/presentations16eu/07.pdf.

Also the error refers to Ssl.read and the snippet you posted is about write, could you show how your Ssl.read code looks like? (e.g. Ssl.read doesn’t like being code with a buffer length of 0).

Thanks a lot for the idea :slight_smile:

WireShark did the trick: this “bad” service sends two websocket frames in one tcp packet where second frame has zero payload length. Naturally, my Websocket implementation improperly handled frames with zero payload which lead to missing of Ping frames and closing of TCP connection by remote server.

Thanks again, Z.