Browse code

tls: tls state is now separate from tcp state

- tls connection state is now kept separately from the tcp state.
- update tls_h_fix_read_conn() to what tcp expects now.

Closes: FlySpray#14.

Andrei Pelinescu-Onciul authored on 21/09/2009 16:43:37
Showing 4 changed files
... ...
@@ -33,6 +33,8 @@
33 33
  * --------
34 34
  *  2007-01-26  openssl kerberos malloc bug detection/workaround (andrei)
35 35
  *  2007-02-23  openssl low memory bugs workaround (andrei)
36
+ *  2009-09-21  tls connection state is now kept in c->extra_data (no
37
+ *               longer shared with tcp state) (andrei)
36 38
  */
37 39
 
38 40
 #include <sys/poll.h>
... ...
@@ -68,6 +70,7 @@ static int tls_complete_init(struct tcp_connection* c)
68 70
 	tls_domain_t* dom;
69 71
 	struct tls_extra_data* data = 0;
70 72
 	tls_cfg_t* cfg;
73
+	enum tls_conn_states state;
71 74
 
72 75
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
73 76
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
... ...
@@ -90,12 +93,17 @@ static int tls_complete_init(struct tcp_connection* c)
90 93
 	      */
91 94
 	cfg->ref_count++;
92 95
 
93
-	if (c->state == S_CONN_ACCEPT) {
94
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV, &c->rcv.dst_ip, c->rcv.dst_port);
95
-	} else if (c->state == S_CONN_CONNECT) {
96
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI, &c->rcv.dst_ip, c->rcv.dst_port);
96
+	if (c->flags & F_CONN_PASSIVE) {
97
+		state=S_TLS_ACCEPTING;
98
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV,
99
+								&c->rcv.dst_ip, c->rcv.dst_port);
97 100
 	} else {
98
-		BUG("Invalid connection state (bug in TCP code)\n");
101
+		state=S_TLS_CONNECTING;
102
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI,
103
+								&c->rcv.dst_ip, c->rcv.dst_port);
104
+	}
105
+	if (unlikely(c->state<0)) {
106
+		BUG("Invalid connection (state %d)\n", c->state);
99 107
 		goto error;
100 108
 	}
101 109
 	DBG("Using TLS domain %s\n", tls_domain_str(dom));
... ...
@@ -108,6 +116,7 @@ static int tls_complete_init(struct tcp_connection* c)
108 116
 	memset(data, '\0', sizeof(struct tls_extra_data));
109 117
 	data->ssl = SSL_new(dom->ctx[process_no]);
110 118
 	data->cfg = cfg;
119
+	data->state = state;
111 120
 
112 121
 	if (data->ssl == 0) {
113 122
 		TLS_ERR("Failed to create SSL structure:");
... ...
@@ -127,7 +136,6 @@ static int tls_complete_init(struct tcp_connection* c)
127 136
 	cfg->ref_count--;
128 137
 	if (data) shm_free(data);
129 138
  error2:
130
-	c->state = S_CONN_BAD;
131 139
 	return -1;
132 140
 }
133 141
 
... ...
@@ -300,24 +308,27 @@ static int tls_accept(struct tcp_connection *c, int* error)
300 308
 	int ret, err, ssl_err;
301 309
 	SSL *ssl;
302 310
 	X509* cert;
311
+	struct tls_extra_data* tls_c;
303 312
 
304
-	if (c->state != S_CONN_ACCEPT) {
305
-		BUG("Invalid connection state (bug in TLS code)\n");
306
-		     /* Not critical */
307
-		return 0;
308
-	}
309 313
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
310 314
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
311 315
 				" operation: %lu\n", shm_available());
312 316
 		goto err;
313 317
 	}
314
-
315
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
318
+	
319
+	tls_c=(struct tls_extra_data*)c->extra_data;
320
+	ssl=tls_c->ssl;
321
+	
322
+	if (tls_c->state != S_TLS_ACCEPTING) {
323
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
324
+		/* Not critical */
325
+		return 0;
326
+	}
316 327
 	ret = SSL_accept(ssl);
317 328
 	if (ret == 1) {
318 329
 		DBG("TLS accept successful\n");
319
-		c->state = S_CONN_OK;
320
-		LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n", 
330
+		tls_c->state = S_TLS_ESTABLISHED;
331
+		LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n",
321 332
 		    ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
322 333
 		    SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), 
323 334
 		    SSL_get_cipher_bits(ssl, 0)
... ...
@@ -383,8 +394,7 @@ static int tls_accept(struct tcp_connection *c, int* error)
383 394
 		}
384 395
 	}
385 396
 	return 0;
386
- err:
387
-	c->state = S_CONN_BAD;
397
+err:
388 398
 	return -1;
389 399
 }
390 400
 
... ...
@@ -397,23 +407,26 @@ static int tls_connect(struct tcp_connection *c, int* error)
397 407
 	SSL *ssl;
398 408
 	int ret, err, ssl_err;
399 409
 	X509* cert;
410
+	struct tls_extra_data* tls_c;
400 411
 
401
-	if (c->state != S_CONN_CONNECT) {
402
-		BUG("Invalid connection state\n");
403
-		     /* Not critical */
404
-		return 0;
405
-	}
406 412
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
407 413
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
408 414
 				" operation: %lu\n", shm_available());
409 415
 		goto err;
410 416
 	}
411 417
 
412
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
418
+	tls_c=(struct tls_extra_data*)c->extra_data;
419
+	ssl=tls_c->ssl;
420
+	
421
+	if (tls_c->state != S_TLS_CONNECTING) {
422
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
423
+		/* Not critical */
424
+		return 0;
425
+	}
413 426
 	ret = SSL_connect(ssl);
414 427
 	if (ret == 1) {
415 428
 		DBG("TLS connect successuful\n");
416
-		c->state = S_CONN_OK;
429
+		tls_c->state = S_TLS_ESTABLISHED;
417 430
 		LOG(tls_log, "tls_connect: new connection to %s:%d using %s %s %d\n", 
418 431
 		    ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
419 432
 		    SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl),
... ...
@@ -481,8 +494,7 @@ static int tls_connect(struct tcp_connection *c, int* error)
481 494
 		}
482 495
 	}
483 496
 	return 0;
484
- err:
485
-	c->state = S_CONN_BAD;
497
+err:
486 498
 	return -1;
487 499
 }
488 500
 
... ...
@@ -707,17 +719,19 @@ int tls_h_blocking_write(struct tcp_connection *c, int fd, const char *buf,
707 719
 	int err, n, ticks, tout;
708 720
 	fd_set sel_set;
709 721
 	struct timeval timeout;
722
+	struct tls_extra_data* tls_c;
710 723
 	
711 724
 	n = 0;
712 725
 	if (tls_update_fd(c, fd) < 0) goto error;
726
+	tls_c=(struct tls_extra_data*)c->extra_data;
713 727
 again:
714 728
 	err = 0;
715 729
 	     /* first try  a "fast" write -- avoid the extra select call,
716 730
 	      * we might get lucky and not need it */
717
-	if (c->state == S_CONN_CONNECT) {
731
+	if (tls_c->state == S_TLS_CONNECTING) {
718 732
 		if (tls_connect(c, &err) < 0) goto error;
719 733
 		tout = tls_handshake_timeout;
720
-	} else if (c->state == S_CONN_ACCEPT) {
734
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
721 735
 		if (tls_accept(c, &err) < 0) goto error;
722 736
 		tout = tls_handshake_timeout;
723 737
 	} else {
... ...
@@ -806,17 +820,19 @@ int tls_h_nonblocking_write(struct tcp_connection *c, int fd, const char *buf,
806 820
 			  unsigned int len)
807 821
 {
808 822
 	int err, n;
823
+	struct tls_extra_data* tls_c;
809 824
 	
810 825
 	n = 0;
811 826
 	if (tls_update_fd(c, fd) < 0) goto error;
827
+	tls_c=(struct tls_extra_data*)c->extra_data;
812 828
 again:
813 829
 	err = 0;
814
-	if (c->state == S_CONN_CONNECT) {
830
+	if (tls_c->state == S_TLS_CONNECTING) {
815 831
 		if (tls_connect(c, &err) < 0) goto error;
816
-	} else if (c->state == S_CONN_ACCEPT) {
832
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
817 833
 		if (tls_accept(c, &err) < 0) goto error;
818 834
 	}
819
-	if (c->state!=S_CONN_CONNECT && c->state!=S_CONN_ACCEPT){
835
+	if (tls_c->state!=S_TLS_CONNECTING && tls_c->state!=S_TLS_ACCEPTING){
820 836
 		n = tls_write(c, buf, len, &err);
821 837
 		if (n < 0) {
822 838
 			DBG("tls_write error %d (ssl %d)\n", n, err);
... ...
@@ -857,8 +873,8 @@ end:
857 873
 
858 874
 
859 875
 /*
860
- * called only when a connection is in S_CONN_OK, we do not have to care
861
- * about accepting or connecting here, each modification of ssl data
876
+ * called only when a connection is in S_TLS_ESTABLISHED, we do not have to
877
+ * care about accepting or connecting here. Each modification of ssl data
862 878
  * structures has to be protected, another process might ask for the same
863 879
  * connection and attempt write to it which would result in updating the
864 880
  * ssl structures 
... ...
@@ -945,40 +961,67 @@ int tls_h_read(struct tcp_connection * c)
945 961
 
946 962
 /*
947 963
  * called before tls_read, the this function should attempt tls_accept or
948
- * tls_connect depending on the state of the connection, if this function
949
- * does not transit a connection into S_CONN_OK then tcp layer would not
964
+ * tls_connect depending on the state of the connection.
965
+ * If this function does not return 1, then the tcp layer would not
950 966
  * call tcp_read 
967
+ * @return  1 success, 0 try again (don't attempt tls_read()), -1 error
951 968
  */
952 969
 int tls_h_fix_read_conn(struct tcp_connection *c)
953 970
 {
954 971
 	int ret;
955
-	ret = 0;
956
-
957
-	switch (c->state) {
958
-	case S_CONN_ACCEPT:
972
+	struct tls_extra_data* tls_c;
973
+	
974
+	ret = -1;
975
+	tls_c = 0;
976
+	if (unlikely(c->extra_data==0)){
959 977
 		lock_get(&c->write_lock);
960
-		     /* It might have changed meanwhile */
961
-		if (c->state == S_CONN_ACCEPT) {
962
-			ret = tls_update_fd(c, c->fd);
963
-			if (ret == 0) ret = tls_accept(c, 0);
964
-			else ret = -1;
965
-		}
978
+			if (unlikely(tls_update_fd(c, c->fd) < 0)){
979
+				ret = -1;
980
+			} else {
981
+				tls_c=(struct tls_extra_data*)c->extra_data;
982
+				switch(tls_c->state){
983
+					case S_TLS_ACCEPTING:
984
+						ret=tls_accept(c, 0);
985
+						break;
986
+					case S_TLS_CONNECTING:
987
+						ret=tls_connect(c, 0);
988
+						break;
989
+					default:
990
+						/* fall through */
991
+						ret=1;
992
+						break;
993
+				}
994
+			}
966 995
 		lock_release(&c->write_lock);
967
-		break;
968
-		
969
-	case S_CONN_CONNECT:
970
-		lock_get(&c->write_lock);
971
-		     /* It might have changed meanwhile */
972
-		if (c->state == S_CONN_CONNECT) {
973
-			ret = tls_update_fd(c, c->fd);
974
-			if (ret == 0) ret = tls_connect(c, 0);
975
-			else ret = -1;
996
+	} else {
997
+		tls_c=(struct tls_extra_data*)c->extra_data;
998
+		switch (tls_c->state) {
999
+			case S_TLS_ACCEPTING:
1000
+				lock_get(&c->write_lock);
1001
+					tls_c=(struct tls_extra_data*)c->extra_data;
1002
+					/* It might have changed meanwhile */
1003
+					if (likely(tls_c->state == S_TLS_ACCEPTING)) {
1004
+						ret = tls_update_fd(c, c->fd);
1005
+						if (ret == 0) ret = tls_accept(c, 0);
1006
+						else ret = -1;
1007
+					}
1008
+				lock_release(&c->write_lock);
1009
+			break;
1010
+			case S_TLS_CONNECTING:
1011
+				lock_get(&c->write_lock);
1012
+					tls_c=(struct tls_extra_data*)c->extra_data;
1013
+					/* It might have changed meanwhile */
1014
+					if (likely(tls_c->state == S_TLS_CONNECTING)) {
1015
+						ret = tls_update_fd(c, c->fd);
1016
+						if (ret == 0) ret = tls_connect(c, 0);
1017
+						else ret = -1;
1018
+					}
1019
+				lock_release(&c->write_lock);
1020
+			break;
1021
+		default: /* fall through */
1022
+			ret=1;
1023
+			break;
976 1024
 		}
977
-		lock_release(&c->write_lock);
978
-		break;
979
-		
980
-	default: /* fall through */
981
-		break;
982 1025
 	}
983
-	return ret;
1026
+	return (ret>=0)?(tls_c->state==S_TLS_ESTABLISHED):ret;
984 1027
 }
... ...
@@ -36,9 +36,17 @@
36 36
 #include "../../tcp_conn.h"
37 37
 #include "tls_domain.h"
38 38
 
39
+enum tls_conn_states {
40
+						S_TLS_NONE = 0,
41
+						S_TLS_ACCEPTING,
42
+						S_TLS_CONNECTING,
43
+						S_TLS_ESTABLISHED
44
+					};
45
+
39 46
 struct tls_extra_data {
40 47
 	tls_cfg_t* cfg; /* Configuration used for this connection */
41 48
 	SSL* ssl;       /* SSL context used for the connection */
49
+	enum  tls_conn_states state;
42 50
 };
43 51
 
44 52
 /*
... ...
@@ -33,6 +33,8 @@
33 33
  * --------
34 34
  *  2007-01-26  openssl kerberos malloc bug detection/workaround (andrei)
35 35
  *  2007-02-23  openssl low memory bugs workaround (andrei)
36
+ *  2009-09-21  tls connection state is now kept in c->extra_data (no
37
+ *               longer shared with tcp state) (andrei)
36 38
  */
37 39
 
38 40
 #include <sys/poll.h>
... ...
@@ -68,6 +70,7 @@ static int tls_complete_init(struct tcp_connection* c)
68 70
 	tls_domain_t* dom;
69 71
 	struct tls_extra_data* data = 0;
70 72
 	tls_cfg_t* cfg;
73
+	enum tls_conn_states state;
71 74
 
72 75
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
73 76
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
... ...
@@ -90,12 +93,17 @@ static int tls_complete_init(struct tcp_connection* c)
90 93
 	      */
91 94
 	cfg->ref_count++;
92 95
 
93
-	if (c->state == S_CONN_ACCEPT) {
94
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV, &c->rcv.dst_ip, c->rcv.dst_port);
95
-	} else if (c->state == S_CONN_CONNECT) {
96
-		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI, &c->rcv.dst_ip, c->rcv.dst_port);
96
+	if (c->flags & F_CONN_PASSIVE) {
97
+		state=S_TLS_ACCEPTING;
98
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_SRV,
99
+								&c->rcv.dst_ip, c->rcv.dst_port);
97 100
 	} else {
98
-		BUG("Invalid connection state (bug in TCP code)\n");
101
+		state=S_TLS_CONNECTING;
102
+		dom = tls_lookup_cfg(cfg, TLS_DOMAIN_CLI,
103
+								&c->rcv.dst_ip, c->rcv.dst_port);
104
+	}
105
+	if (unlikely(c->state<0)) {
106
+		BUG("Invalid connection (state %d)\n", c->state);
99 107
 		goto error;
100 108
 	}
101 109
 	DBG("Using TLS domain %s\n", tls_domain_str(dom));
... ...
@@ -108,6 +116,7 @@ static int tls_complete_init(struct tcp_connection* c)
108 116
 	memset(data, '\0', sizeof(struct tls_extra_data));
109 117
 	data->ssl = SSL_new(dom->ctx[process_no]);
110 118
 	data->cfg = cfg;
119
+	data->state = state;
111 120
 
112 121
 	if (data->ssl == 0) {
113 122
 		TLS_ERR("Failed to create SSL structure:");
... ...
@@ -127,7 +136,6 @@ static int tls_complete_init(struct tcp_connection* c)
127 136
 	cfg->ref_count--;
128 137
 	if (data) shm_free(data);
129 138
  error2:
130
-	c->state = S_CONN_BAD;
131 139
 	return -1;
132 140
 }
133 141
 
... ...
@@ -300,24 +308,27 @@ static int tls_accept(struct tcp_connection *c, int* error)
300 308
 	int ret, err, ssl_err;
301 309
 	SSL *ssl;
302 310
 	X509* cert;
311
+	struct tls_extra_data* tls_c;
303 312
 
304
-	if (c->state != S_CONN_ACCEPT) {
305
-		BUG("Invalid connection state (bug in TLS code)\n");
306
-		     /* Not critical */
307
-		return 0;
308
-	}
309 313
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
310 314
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
311 315
 				" operation: %lu\n", shm_available());
312 316
 		goto err;
313 317
 	}
314
-
315
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
318
+	
319
+	tls_c=(struct tls_extra_data*)c->extra_data;
320
+	ssl=tls_c->ssl;
321
+	
322
+	if (tls_c->state != S_TLS_ACCEPTING) {
323
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
324
+		/* Not critical */
325
+		return 0;
326
+	}
316 327
 	ret = SSL_accept(ssl);
317 328
 	if (ret == 1) {
318 329
 		DBG("TLS accept successful\n");
319
-		c->state = S_CONN_OK;
320
-		LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n", 
330
+		tls_c->state = S_TLS_ESTABLISHED;
331
+		LOG(tls_log, "tls_accept: new connection from %s:%d using %s %s %d\n",
321 332
 		    ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
322 333
 		    SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl), 
323 334
 		    SSL_get_cipher_bits(ssl, 0)
... ...
@@ -383,8 +394,7 @@ static int tls_accept(struct tcp_connection *c, int* error)
383 394
 		}
384 395
 	}
385 396
 	return 0;
386
- err:
387
-	c->state = S_CONN_BAD;
397
+err:
388 398
 	return -1;
389 399
 }
390 400
 
... ...
@@ -397,23 +407,26 @@ static int tls_connect(struct tcp_connection *c, int* error)
397 407
 	SSL *ssl;
398 408
 	int ret, err, ssl_err;
399 409
 	X509* cert;
410
+	struct tls_extra_data* tls_c;
400 411
 
401
-	if (c->state != S_CONN_CONNECT) {
402
-		BUG("Invalid connection state\n");
403
-		     /* Not critical */
404
-		return 0;
405
-	}
406 412
 	if (LOW_MEM_NEW_CONNECTION_TEST()){
407 413
 		ERR("tls: ssl bug #1491 workaround: not enough memory for safe"
408 414
 				" operation: %lu\n", shm_available());
409 415
 		goto err;
410 416
 	}
411 417
 
412
-	ssl = ((struct tls_extra_data*)c->extra_data)->ssl;
418
+	tls_c=(struct tls_extra_data*)c->extra_data;
419
+	ssl=tls_c->ssl;
420
+	
421
+	if (tls_c->state != S_TLS_CONNECTING) {
422
+		BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
423
+		/* Not critical */
424
+		return 0;
425
+	}
413 426
 	ret = SSL_connect(ssl);
414 427
 	if (ret == 1) {
415 428
 		DBG("TLS connect successuful\n");
416
-		c->state = S_CONN_OK;
429
+		tls_c->state = S_TLS_ESTABLISHED;
417 430
 		LOG(tls_log, "tls_connect: new connection to %s:%d using %s %s %d\n", 
418 431
 		    ip_addr2a(&c->rcv.src_ip), c->rcv.src_port,
419 432
 		    SSL_get_cipher_version(ssl), SSL_get_cipher_name(ssl),
... ...
@@ -481,8 +494,7 @@ static int tls_connect(struct tcp_connection *c, int* error)
481 494
 		}
482 495
 	}
483 496
 	return 0;
484
- err:
485
-	c->state = S_CONN_BAD;
497
+err:
486 498
 	return -1;
487 499
 }
488 500
 
... ...
@@ -707,17 +719,19 @@ int tls_h_blocking_write(struct tcp_connection *c, int fd, const char *buf,
707 719
 	int err, n, ticks, tout;
708 720
 	fd_set sel_set;
709 721
 	struct timeval timeout;
722
+	struct tls_extra_data* tls_c;
710 723
 	
711 724
 	n = 0;
712 725
 	if (tls_update_fd(c, fd) < 0) goto error;
726
+	tls_c=(struct tls_extra_data*)c->extra_data;
713 727
 again:
714 728
 	err = 0;
715 729
 	     /* first try  a "fast" write -- avoid the extra select call,
716 730
 	      * we might get lucky and not need it */
717
-	if (c->state == S_CONN_CONNECT) {
731
+	if (tls_c->state == S_TLS_CONNECTING) {
718 732
 		if (tls_connect(c, &err) < 0) goto error;
719 733
 		tout = tls_handshake_timeout;
720
-	} else if (c->state == S_CONN_ACCEPT) {
734
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
721 735
 		if (tls_accept(c, &err) < 0) goto error;
722 736
 		tout = tls_handshake_timeout;
723 737
 	} else {
... ...
@@ -805,17 +819,19 @@ int tls_h_nonblocking_write(struct tcp_connection *c, int fd, const char *buf,
805 819
 			  unsigned int len)
806 820
 {
807 821
 	int err, n;
822
+	struct tls_extra_data* tls_c;
808 823
 	
809 824
 	n = 0;
810 825
 	if (tls_update_fd(c, fd) < 0) goto error;
826
+	tls_c=(struct tls_extra_data*)c->extra_data;
811 827
 again:
812 828
 	err = 0;
813
-	if (c->state == S_CONN_CONNECT) {
829
+	if (tls_c->state == S_TLS_CONNECTING) {
814 830
 		if (tls_connect(c, &err) < 0) goto error;
815
-	} else if (c->state == S_CONN_ACCEPT) {
831
+	} else if (tls_c->state == S_TLS_ACCEPTING) {
816 832
 		if (tls_accept(c, &err) < 0) goto error;
817 833
 	}
818
-	if (c->state!=S_CONN_CONNECT && c->state!=S_CONN_ACCEPT){
834
+	if (tls_c->state!=S_TLS_CONNECTING && tls_c->state!=S_TLS_ACCEPTING){
819 835
 		n = tls_write(c, buf, len, &err);
820 836
 		if (n < 0) {
821 837
 			DBG("tls_write error %d (ssl %d)\n", n, err);
... ...
@@ -856,8 +872,8 @@ end:
856 872
 
857 873
 
858 874
 /*
859
- * called only when a connection is in S_CONN_OK, we do not have to care
860
- * about accepting or connecting here, each modification of ssl data
875
+ * called only when a connection is in S_TLS_ESTABLISHED, we do not have to
876
+ * care about accepting or connecting here. Each modification of ssl data
861 877
  * structures has to be protected, another process might ask for the same
862 878
  * connection and attempt write to it which would result in updating the
863 879
  * ssl structures 
... ...
@@ -944,40 +960,67 @@ int tls_h_read(struct tcp_connection * c)
944 960
 
945 961
 /*
946 962
  * called before tls_read, the this function should attempt tls_accept or
947
- * tls_connect depending on the state of the connection, if this function
948
- * does not transit a connection into S_CONN_OK then tcp layer would not
963
+ * tls_connect depending on the state of the connection.
964
+ * If this function does not return 1, then the tcp layer would not
949 965
  * call tcp_read 
966
+ * @return  1 success, 0 try again (don't attempt tls_read()), -1 error
950 967
  */
951 968
 int tls_h_fix_read_conn(struct tcp_connection *c)
952 969
 {
953 970
 	int ret;
954
-	ret = 0;
955
-
956
-	switch (c->state) {
957
-	case S_CONN_ACCEPT:
971
+	struct tls_extra_data* tls_c;
972
+	
973
+	ret = -1;
974
+	tls_c = 0;
975
+	if (unlikely(c->extra_data==0)){
958 976
 		lock_get(&c->write_lock);
959
-		     /* It might have changed meanwhile */
960
-		if (c->state == S_CONN_ACCEPT) {
961
-			ret = tls_update_fd(c, c->fd);
962
-			if (ret == 0) ret = tls_accept(c, 0);
963
-			else ret = -1;
964
-		}
977
+			if (unlikely(tls_update_fd(c, c->fd) < 0)){
978
+				ret = -1;
979
+			} else {
980
+				tls_c=(struct tls_extra_data*)c->extra_data;
981
+				switch(tls_c->state){
982
+					case S_TLS_ACCEPTING:
983
+						ret=tls_accept(c, 0);
984
+						break;
985
+					case S_TLS_CONNECTING:
986
+						ret=tls_connect(c, 0);
987
+						break;
988
+					default:
989
+						/* fall through */
990
+						ret=1;
991
+						break;
992
+				}
993
+			}
965 994
 		lock_release(&c->write_lock);
966
-		break;
967
-		
968
-	case S_CONN_CONNECT:
969
-		lock_get(&c->write_lock);
970
-		     /* It might have changed meanwhile */
971
-		if (c->state == S_CONN_CONNECT) {
972
-			ret = tls_update_fd(c, c->fd);
973
-			if (ret == 0) ret = tls_connect(c, 0);
974
-			else ret = -1;
995
+	} else {
996
+		tls_c=(struct tls_extra_data*)c->extra_data;
997
+		switch (tls_c->state) {
998
+			case S_TLS_ACCEPTING:
999
+				lock_get(&c->write_lock);
1000
+					tls_c=(struct tls_extra_data*)c->extra_data;
1001
+					/* It might have changed meanwhile */
1002
+					if (likely(tls_c->state == S_TLS_ACCEPTING)) {
1003
+						ret = tls_update_fd(c, c->fd);
1004
+						if (ret == 0) ret = tls_accept(c, 0);
1005
+						else ret = -1;
1006
+					}
1007
+				lock_release(&c->write_lock);
1008
+			break;
1009
+			case S_TLS_CONNECTING:
1010
+				lock_get(&c->write_lock);
1011
+					tls_c=(struct tls_extra_data*)c->extra_data;
1012
+					/* It might have changed meanwhile */
1013
+					if (likely(tls_c->state == S_TLS_CONNECTING)) {
1014
+						ret = tls_update_fd(c, c->fd);
1015
+						if (ret == 0) ret = tls_connect(c, 0);
1016
+						else ret = -1;
1017
+					}
1018
+				lock_release(&c->write_lock);
1019
+			break;
1020
+		default: /* fall through */
1021
+			ret=1;
1022
+			break;
975 1023
 		}
976
-		lock_release(&c->write_lock);
977
-		break;
978
-		
979
-	default: /* fall through */
980
-		break;
981 1024
 	}
982
-	return ret;
1025
+	return (ret>=0)?(tls_c->state==S_TLS_ESTABLISHED):ret;
983 1026
 }
... ...
@@ -36,9 +36,17 @@
36 36
 #include "../../tcp_conn.h"
37 37
 #include "tls_domain.h"
38 38
 
39
+enum tls_conn_states {
40
+						S_TLS_NONE = 0,
41
+						S_TLS_ACCEPTING,
42
+						S_TLS_CONNECTING,
43
+						S_TLS_ESTABLISHED
44
+					};
45
+
39 46
 struct tls_extra_data {
40 47
 	tls_cfg_t* cfg; /* Configuration used for this connection */
41 48
 	SSL* ssl;       /* SSL context used for the connection */
49
+	enum  tls_conn_states state;
42 50
 };
43 51
 
44 52
 /*