Non-blocking accept() and connect()

I was trying to do accept() and listen() in a non-blocking way. Pseudo code is below.

/* Non Blocking Accept() */

1) Check whether listening fd is ready for read, by using select();
2) Once ready issue accept(), this will return a new socket fd;

/* Non Blocking Connect() */

1) Issue connect on socket fd;
2) If it is returning EINPROGRESS, check whether fd is ready for write using select();
3) If it is ready check socket state using getsockopt();
4) If no errors, then socket connection is established;

TCP connection establishment is a three-way handshake, see below. Actually it is a 4-way process, but usually server will combine both SYN and ACK in a single packet, so three way handshake.

Client initiates the connection request by sending the SYN, this is what happens when it calls connect(), then it waits for ACK+SYN from server, when client gets ACK+SYN packets, it sends ACK packet and moves the socket to ESTABLISHED state, see TCP state diagram below.

Only point at which client has to wait is when it waits for ACK+SYN packet from server, this is indicated by EINPROGRESS return code from connect() call. When  fd returns from select(), indicating ready for write, it means either some error happended or ACK is send(3-way handshake done) by client in response to ACK+SYN packet from server, we can check for error using getsockopt() call, if no errors then client socket is in ESTABLISHED state, ready for send/receive packets. Client need not call another connect() to ACK the ACK+SYN packet from server, it will be done by the stack/kernel.

On the server side, I was on the impression that accept() is the one which is sending ACK+SYN packet to client, so accept() pseudo code may not work properly, it may not eliminate one delay (sending ACK+SYN and waiting for ACK from client)

Actually accept() works in a different way, stack/kernel is the one doing the 3-way handshake and then new connection availability is notified to the application(server). TCP stack maintains two queues, one incomplete connection queue and one completed connection queue. Connection which are in SYN_RCVD state(i.e. send ACK+SYN packet in response to SYN from client) are in incomplete connection queue, connections which are in incomplete connection queue are moved to completed connection queue when it receives ACK from client in response to ACK+SYN. Accept() will be successful only if there is any connection in completed connection queue, select() will return ready for read only if there is any connection in completed connection queue.

So Accept() is not the one which does 3-way handshake, but it simply returns new socket fd, if there any connections in completed connection queue, so our pseudo code will work correctly.

SSL/TLS sockets programming using openssl and polarssl

I was trying to do some modifications to mongoose http server to use polarssl, to do that I tried to understand openssl and polarssl libraries, for that I wrote some example client/server programs, See https://github.com/CloudFundoo/SSL-TLS-clientserver, may be useful.

To compile this with libssl, first install openssl(or libssl) library, dev package and tools package.

Then sync our example source code and give “make libssl”, this will give both server and client executables.

Compiling with polarssl has some problems, first we need to compile the polarssl library since we don’t have polarssl packages for ubuntu.

Download polarssl source tarball and unzip to some folder, then issue following commands

$make 
$make install
$make -C library/ shared

“make all/make” will not create shared library, so we need to issue “make shared” for that. After creating shared library copy it to “/usr/lib”. Polarssl library installation is complete now.

Now issue “make polarssl” in our example directory, it will give both server and client executables.

Next step is creating certificate file, to generate CA, server and client certificates, follow below instructions

##generate CA cert and key files
$openssl genrsa -des3 -out ca.key 4096
$openssl req -new -x509 -days 365 -key ca.key -out ca.crt

##generate Server cert and key files
$openssl genrsa -des3 -out ssl_server.key 4096
$openssl req -new -key ssl_server.key -out ssl_server.csr

##Sign using CA
$openssl x509 -req -days 365 -in ssl_server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out ssl_server.crt

##generate Client cert and key files
$openssl genrsa -des3 -out ssl_client.key 4096
$openssl req -new -key ssl_client.key -out ssl_client.csr

##Sign using CA
$openssl x509 -req -days 365 -in ssl_client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out ssl_client.crt