Browse code

tcp: new tls hooks interface and async tls changes

- new tls hooks interface that better accommodates tls async use.
Changed read() (takes an extra flags parameter now), removed
blocking_write() and fix_read_con(), added do_send() and
fst_send() (both of them handle snd_flags now and might return a
command that should be sent to tcp_main).
- more tcp send functions (tcpconn_1st_send(),
tcpconn_send_unsafe()) and more send functions exported
(tls_int_send.h) for use from the tls module.
- split tcp_read() into tcp_read() and tcp_read_data() and
exported tcp_read_data() (tcp_read.h).
- support for repeating a tcp_read() if indicated
(RD_CONN_REPEAT_READ), needed for tls.

Andrei Pelinescu-Onciul authored on 20/05/2010 14:00:29
Showing 5 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,50 @@
0
+/* 
1
+ * $Id$
2
+ * 
3
+ * Copyright (C) 2010 iptelorg GmbH
4
+ *
5
+ * Permission to use, copy, modify, and distribute this software for any
6
+ * purpose with or without fee is hereby granted, provided that the above
7
+ * copyright notice and this permission notice appear in all copies.
8
+ *
9
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ */
17
+/** internal tcp send functions (use with care).
18
+ * @file tcp_int_send.h
19
+ */
20
+/*
21
+ * History:
22
+ * --------
23
+ *  2010-03-23  initial version (andrei)
24
+*/
25
+
26
+#ifndef __tcp_int_send_h
27
+#define __tcp_int_send_h
28
+
29
+#include "tcp_conn.h"
30
+
31
+int tcpconn_do_send(int fd, struct tcp_connection* c,
32
+							char* buf, unsigned len,
33
+							snd_flags_t send_flags, long* resp, int locked);
34
+
35
+int tcpconn_1st_send(int fd, struct tcp_connection* c,
36
+							char* buf, unsigned len,
37
+							snd_flags_t send_flags, long* resp, int locked);
38
+
39
+int tcpconn_send_unsafe(int fd, struct tcp_connection *c,
40
+						char* buf, unsigned len, snd_flags_t send_flags);
41
+
42
+/* direct non-blocking, unsafe (assumes locked) send on a tcp connection */
43
+int _tcpconn_write_nb(int fd, struct tcp_connection* c,
44
+									char* buf, int len);
45
+
46
+
47
+#endif /*__tcp_int_send_h*/
48
+
49
+/* vi: set ts=4 sw=4 tw=79:ai:cindent: */
... ...
@@ -103,13 +103,13 @@
103 103
  *  2009-04-09  tcp ev and tcp stats macros added (andrei)
104 104
  *  2009-09-15  support for force connection reuse and close after send
105 105
  *               send flags (andrei)
106
+ *  2010-03-23  tcp_send() split in 3 smaller functions (andrei)
106 107
  */
107 108
 
108
-/*!
109
- * \file
110
- * \brief SIP-router core :: 
111
- * \ingroup core
112
- * Module: \ref core
109
+/** tcp main/dispatcher and tcp send functions.
110
+ * @file tcp_main.c
111
+ * @ingroup core
112
+ * Module: @ref core
113 113
  */
114 114
 
115 115
 
... ...
@@ -165,6 +165,7 @@
165 165
 #include "sr_module.h"
166 166
 #include "tcp_server.h"
167 167
 #include "tcp_init.h"
168
+#include "tcp_int_send.h"
168 169
 #include "tcp_stats.h"
169 170
 #include "tcp_ev.h"
170 171
 #include "tsend.h"
... ...
@@ -631,10 +632,6 @@ end:
631 631
 
632 632
 
633 633
 
634
-inline static int _tcpconn_write_nb(int fd, struct tcp_connection* c,
635
-									char* buf, int len);
636
-
637
-
638 634
 #ifdef TCP_ASYNC
639 635
 
640 636
 
... ...
@@ -1717,10 +1714,6 @@ inline static void tcp_fd_cache_add(struct tcp_connection *c, int fd)
1717 1717
 
1718 1718
 inline static int tcpconn_chld_put(struct tcp_connection* tcpconn);
1719 1719
 
1720
-static int tcpconn_do_send(int fd, struct tcp_connection* c,
1721
-							char* buf, unsigned len,
1722
-							snd_flags_t send_flags, long* resp);
1723
-
1724 1720
 static int tcpconn_send_put(struct tcp_connection* c, char* buf, unsigned len,
1725 1721
 							snd_flags_t send_flags);
1726 1722
 
... ...
@@ -1766,257 +1759,201 @@ int tcp_send(struct dest_info* dst, union sockaddr_union* from,
1766 1766
 			}
1767 1767
 		}
1768 1768
 	}
1769
-/* no_id: */
1770
-		if (unlikely((c==0) || tcpconn_close_after_send(c))){
1771
-			if (unlikely(c)){
1772
-				/* can't use c if it's marked as close-after-send  =>
1773
-				   release it and try opening new one */
1774
-				tcpconn_chld_put(c); /* release c (dec refcnt & free on 0) */
1775
-				c=0;
1776
-			}
1777
-			/* check if connect() is disabled */
1778
-			if (unlikely((dst->send_flags.f & SND_F_FORCE_CON_REUSE) ||
1779
-							cfg_get(tcp, tcp_cfg, no_connect)))
1780
-				return -1;
1781
-			DBG("tcp_send: no open tcp connection found, opening new one\n");
1782
-			/* create tcp connection */
1783
-			if (likely(from==0)){
1784
-				/* check to see if we have to use a specific source addr. */
1785
-				switch (dst->to.s.sa_family) {
1786
-					case AF_INET:
1787
-							from = tcp_source_ipv4;
1788
-						break;
1769
+	/* connection not found or unusable => open a new one and send on it */
1770
+	if (unlikely((c==0) || tcpconn_close_after_send(c))){
1771
+		if (unlikely(c)){
1772
+			/* can't use c if it's marked as close-after-send  =>
1773
+			   release it and try opening new one */
1774
+			tcpconn_chld_put(c); /* release c (dec refcnt & free on 0) */
1775
+			c=0;
1776
+		}
1777
+		/* check if connect() is disabled */
1778
+		if (unlikely((dst->send_flags.f & SND_F_FORCE_CON_REUSE) ||
1779
+						cfg_get(tcp, tcp_cfg, no_connect)))
1780
+			return -1;
1781
+		DBG("tcp_send: no open tcp connection found, opening new one\n");
1782
+		/* create tcp connection */
1783
+		if (likely(from==0)){
1784
+			/* check to see if we have to use a specific source addr. */
1785
+			switch (dst->to.s.sa_family) {
1786
+				case AF_INET:
1787
+						from = tcp_source_ipv4;
1788
+					break;
1789 1789
 #ifdef USE_IPV6
1790
-					case AF_INET6:
1791
-							from = tcp_source_ipv6;
1792
-						break;
1790
+				case AF_INET6:
1791
+						from = tcp_source_ipv6;
1792
+					break;
1793 1793
 #endif
1794
-					default:
1795
-						/* error, bad af, ignore ... */
1796
-						break;
1797
-				}
1794
+				default:
1795
+					/* error, bad af, ignore ... */
1796
+					break;
1798 1797
 			}
1798
+		}
1799 1799
 #if defined(TCP_CONNECT_WAIT) && defined(TCP_ASYNC)
1800
-			if (likely(cfg_get(tcp, tcp_cfg, tcp_connect_wait) && 
1801
-						cfg_get(tcp, tcp_cfg, async) )){
1802
-				if (unlikely(*tcp_connections_no >=
1803
-								cfg_get(tcp, tcp_cfg, max_connections))){
1804
-					LOG(L_ERR, "ERROR: tcp_send %s: maximum number of"
1805
-								" connections exceeded (%d/%d)\n",
1806
-								su2a(&dst->to, sizeof(dst->to)),
1807
-								*tcp_connections_no,
1808
-								cfg_get(tcp, tcp_cfg, max_connections));
1809
-					return -1;
1810
-				}
1811
-				c=tcpconn_new(-1, &dst->to, from, 0, dst->proto,
1812
-								S_CONN_CONNECT);
1813
-				if (unlikely(c==0)){
1814
-					LOG(L_ERR, "ERROR: tcp_send %s: could not create new"
1815
-							" connection\n",
1816
-							su2a(&dst->to, sizeof(dst->to)));
1817
-					return -1;
1818
-				}
1819
-				c->flags|=F_CONN_PENDING|F_CONN_FD_CLOSED;
1820
-				tcpconn_set_send_flags(c, dst->send_flags);
1821
-				atomic_set(&c->refcnt, 2); /* ref from here and from main hash
1822
-											 table */
1823
-				/* add it to id hash and aliases */
1824
-				if (unlikely(tcpconn_add(c)==0)){
1825
-					LOG(L_ERR, "ERROR: tcp_send %s: could not add "
1826
-								"connection %p\n",
1827
-								su2a(&dst->to, sizeof(dst->to)),
1828
-									c);
1829
-					_tcpconn_free(c);
1830
-					n=-1;
1831
-					goto end_no_conn;
1832
-				}
1833
-				/* do connect and if src ip or port changed, update the 
1834
-				 * aliases */
1835
-				if (unlikely((fd=tcpconn_finish_connect(c, from))<0)){
1836
-					/* tcpconn_finish_connect will automatically blacklist
1837
-					   on error => no need to do it here */
1838
-					LOG(L_ERR, "ERROR: tcp_send %s: tcpconn_finish_connect(%p)"
1839
-							" failed\n", su2a(&dst->to, sizeof(dst->to)),
1840
-								c);
1841
-					goto conn_wait_error;
1842
-				}
1843
-				/* ? TODO: it might be faster just to queue the write directly
1844
-				 *  and send to main CONN_NEW_PENDING_WRITE */
1845
-				/* delay sending the fd to main after the send */
1846
-				
1847
-				/* NOTE: no lock here, because the connection is marked as
1848
-				 * pending and nobody else will try to write on it. However
1849
-				 * this might produce out-of-order writes. If this is not
1850
-				 * desired either lock before the write or use 
1851
-				 * _wbufq_insert(...) */
1852
-				n=_tcpconn_write_nb(fd, c, buf, len);
1853
-				if (unlikely(n<(int)len)){
1854
-					if ((n>=0) || errno==EAGAIN || errno==EWOULDBLOCK){
1855
-						DBG("tcp_send: pending write on new connection %p "
1856
-								" (%d/%d bytes written)\n", c, n, len);
1857
-						if (n<0) n=0;
1858
-						else{
1859
-							TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1860
-							c->state=S_CONN_OK; /* partial write => connect()
1861
-													ended */
1862
-						}
1863
-						/* add to the write queue */
1864
-						lock_get(&c->write_lock);
1865
-							if (unlikely(_wbufq_insert(c, buf+n, len-n)<0)){
1866
-								lock_release(&c->write_lock);
1867
-								n=-1;
1868
-								LOG(L_ERR, "ERROR: tcp_send %s: EAGAIN and"
1869
-										" write queue full or failed for %p\n",
1870
-										su2a(&dst->to, sizeof(dst->to)),
1871
-										c);
1872
-								goto conn_wait_error;
1873
-							}
1874
-						lock_release(&c->write_lock);
1875
-						/* send to tcp_main */
1876
-						response[0]=(long)c;
1877
-						response[1]=CONN_NEW_PENDING_WRITE;
1878
-						if (unlikely(send_fd(unix_tcp_sock, response, 
1879
-												sizeof(response), fd) <= 0)){
1880
-							LOG(L_ERR, "BUG: tcp_send %s: "
1881
-										"CONN_NEW_PENDING_WRITE  for %p"
1882
-										" failed:" " %s (%d)\n",
1883
-										su2a(&dst->to, sizeof(dst->to)),
1884
-										c, strerror(errno), errno);
1885
-							goto conn_wait_error;
1886
-						}
1887
-						n=len;
1888
-						goto conn_wait_success;
1889
-					}
1890
-					/* if first write failed it's most likely a
1891
-					   connect error */
1892
-					switch(errno){
1893
-						case ENETUNREACH:
1894
-						case EHOSTUNREACH:  /* not posix for send() */
1895
-#ifdef USE_DST_BLACKLIST
1896
-							dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1897
-#endif /* USE_DST_BLACKLIST */
1898
-							TCP_EV_CONNECT_UNREACHABLE(errno, TCP_LADDR(c),
1899
-									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
1900
-							break;
1901
-						case ECONNREFUSED:
1902
-						case ECONNRESET:
1903
-#ifdef USE_DST_BLACKLIST
1904
-							dst_blacklist_add( BLST_ERR_CONNECT, dst, 0);
1905
-#endif /* USE_DST_BLACKLIST */
1906
-							TCP_EV_CONNECT_RST(errno, TCP_LADDR(c),
1907
-									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
1908
-							break;
1909
-						default:
1910
-							TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c),
1911
-									TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
1912
-					}
1913
-					/* error: destroy it directly */
1914
-					TCP_STATS_CONNECT_FAILED();
1915
-					LOG(L_ERR, "ERROR: tcp_send %s: connect & send "
1916
-										" for %p failed:" " %s (%d)\n",
1917
-										su2a(&dst->to, sizeof(dst->to)),
1918
-										c, strerror(errno), errno);
1919
-					goto conn_wait_error;
1920
-				}
1921
-				LOG(L_INFO, "tcp_send: quick connect for %p\n", c);
1922
-				TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1923
-				if (unlikely(dst->send_flags.f & SND_F_CON_CLOSE)){
1924
-					/* if close-after-send requested, don't bother
1925
-					   sending the fd back to tcp_main, try closing it
1926
-					   immediately (no other tcp_send should use it,
1927
-					   because it is marked as close-after-send before
1928
-					   being added to the hash */
1929
-					goto conn_wait_close;
1930
-				}
1931
-				c->state=S_CONN_OK;
1932
-				/* send to tcp_main */
1933
-				response[0]=(long)c;
1934
-				response[1]=CONN_NEW_COMPLETE;
1935
-				if (unlikely(send_fd(unix_tcp_sock, response, 
1936
-										sizeof(response), fd) <= 0)){
1937
-					LOG(L_ERR, "BUG: tcp_send %s: CONN_NEW_COMPLETE  for %p"
1938
-								" failed:" " %s (%d)\n",
1939
-								su2a(&dst->to, sizeof(dst->to)),
1940
-								c, strerror(errno), errno);
1941
-					goto conn_wait_error;
1942
-				}
1943
-				goto conn_wait_success;
1800
+		if (likely(cfg_get(tcp, tcp_cfg, tcp_connect_wait) && 
1801
+					cfg_get(tcp, tcp_cfg, async) )){
1802
+			if (unlikely(*tcp_connections_no >=
1803
+							cfg_get(tcp, tcp_cfg, max_connections))){
1804
+				LOG(L_ERR, "ERROR: tcp_send %s: maximum number of"
1805
+							" connections exceeded (%d/%d)\n",
1806
+							su2a(&dst->to, sizeof(dst->to)),
1807
+							*tcp_connections_no,
1808
+							cfg_get(tcp, tcp_cfg, max_connections));
1809
+				return -1;
1944 1810
 			}
1945
-#endif /* TCP_CONNECT_WAIT  && TCP_ASYNC */
1946
-			if (unlikely((c=tcpconn_connect(&dst->to, from, dst->proto,
1947
-											&dst->send_flags))==0)){
1948
-				LOG(L_ERR, "ERROR: tcp_send %s: connect failed\n",
1949
-								su2a(&dst->to, sizeof(dst->to)));
1811
+			c=tcpconn_new(-1, &dst->to, from, 0, dst->proto,
1812
+							S_CONN_CONNECT);
1813
+			if (unlikely(c==0)){
1814
+				LOG(L_ERR, "ERROR: tcp_send %s: could not create new"
1815
+						" connection\n",
1816
+						su2a(&dst->to, sizeof(dst->to)));
1950 1817
 				return -1;
1951 1818
 			}
1819
+			c->flags|=F_CONN_PENDING|F_CONN_FD_CLOSED;
1952 1820
 			tcpconn_set_send_flags(c, dst->send_flags);
1953
-			if (likely(c->state==S_CONN_OK))
1954
-				TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1955
-			atomic_set(&c->refcnt, 2); /* ref. from here and it will also
1956
-			                              be added in the tcp_main hash */
1957
-			fd=c->s;
1958
-			c->flags|=F_CONN_FD_CLOSED; /* not yet opened in main */
1959
-			/* ? TODO: it might be faster just to queue the write and
1960
-			 * send to main a CONN_NEW_PENDING_WRITE */
1961
-			
1962
-			/* send the new tcpconn to "tcp main" */
1963
-			response[0]=(long)c;
1964
-			response[1]=CONN_NEW;
1965
-			n=send_fd(unix_tcp_sock, response, sizeof(response), c->s);
1966
-			if (unlikely(n<=0)){
1967
-				LOG(L_ERR, "BUG: tcp_send %s: failed send_fd: %s (%d)\n",
1968
-						su2a(&dst->to, sizeof(dst->to)),
1969
-						strerror(errno), errno);
1970
-				/* we can safely delete it, it's not referenced by anybody */
1821
+			atomic_set(&c->refcnt, 2); /* ref from here and from main hash
1822
+										 table */
1823
+			/* add it to id hash and aliases */
1824
+			if (unlikely(tcpconn_add(c)==0)){
1825
+				LOG(L_ERR, "ERROR: tcp_send %s: could not add "
1826
+							"connection %p\n",
1827
+							su2a(&dst->to, sizeof(dst->to)),
1828
+								c);
1971 1829
 				_tcpconn_free(c);
1972 1830
 				n=-1;
1973 1831
 				goto end_no_conn;
1974 1832
 			}
1975
-			/* new connection => send on it directly */
1976
-			n = tcpconn_do_send(fd, c, buf, len, dst->send_flags,
1833
+			/* do connect and if src ip or port changed, update the 
1834
+			 * aliases */
1835
+			if (unlikely((fd=tcpconn_finish_connect(c, from))<0)){
1836
+				/* tcpconn_finish_connect will automatically blacklist
1837
+				   on error => no need to do it here */
1838
+				LOG(L_ERR, "ERROR: tcp_send %s: tcpconn_finish_connect(%p)"
1839
+						" failed\n", su2a(&dst->to, sizeof(dst->to)),
1840
+							c);
1841
+				goto conn_wait_error;
1842
+			}
1843
+			/* ? TODO: it might be faster just to queue the write directly
1844
+			 *  and send to main CONN_NEW_PENDING_WRITE */
1845
+			/* delay sending the fd to main after the send */
1846
+			
1847
+			/* NOTE: no lock here, because the connection is marked as
1848
+			 * pending and nobody else will try to write on it. However
1849
+			 * this might produce out-of-order writes. If this is not
1850
+			 * desired either lock before the write or use 
1851
+			 * _wbufq_insert(...) */
1852
+#ifdef USE_TLS
1853
+			if (unlikely(c->type==PROTO_TLS))
1854
+				n=tls_1st_send(fd, c, buf, len, dst->send_flags,
1977 1855
 									&response[1]);
1978
-			if (unlikely(response[1] != CONN_NOP)) {
1979
-				response[0]=(long)c;
1980
-				if (send_all(unix_tcp_sock, response, sizeof(response)) <= 0) {
1981
-					BUG("tcp_main command %ld sending failed (write):"
1982
-							"%s (%d)\n", response[1], strerror(errno), errno);
1983
-					/* all commands != CONN_NOP returned by tcpconn_do_send()
1984
-					   (CONN_EOF, CONN_ERROR, CONN_QUEUED_WRITE) will auto-dec
1985
-					   refcnt => if sending the command fails we have to
1986
-					   dec. refcnt by hand */
1987
-					tcpconn_chld_put(c); /* deref. it manually */
1988
-					n=-1;
1989
-				}
1990
-				/* here refcnt for c is already decremented => c contents can
1991
-				   no longer be used and refcnt _must_ _not_ be decremented
1992
-				   again on exit */
1993
-				if (unlikely(n < 0 || response[1] == CONN_EOF)) {
1994
-					/* on error or eof, close fd */
1995
-					close(fd);
1996
-				} else if (response[1] == CONN_QUEUED_WRITE) {
1856
+			else
1857
+#endif /* USE_TLS */
1858
+				n=tcpconn_1st_send(fd, c, buf, len, dst->send_flags,
1859
+									&response[1], 0);
1860
+			if (unlikely(n<0))
1861
+				goto conn_wait_error;
1862
+			if (unlikely(response[1]==CONN_EOF)){
1863
+				/* if close-after-send requested, don't bother
1864
+				   sending the fd back to tcp_main, try closing it
1865
+				   immediately (no other tcp_send should use it,
1866
+				   because it is marked as close-after-send before
1867
+				   being added to the hash */
1868
+				goto conn_wait_close;
1869
+			}
1870
+			/* send to tcp_main */
1871
+			response[0]=(long)c;
1872
+			if (unlikely(response[1]!=CONN_NOP &&
1873
+						(send_fd(unix_tcp_sock, response,
1874
+									sizeof(response), fd) <= 0))){
1875
+				LOG(L_ERR, "BUG: tcp_send %s: %ld for %p"
1876
+							" failed:" " %s (%d)\n",
1877
+							su2a(&dst->to, sizeof(dst->to)),
1878
+							response[1], c, strerror(errno), errno);
1879
+				goto conn_wait_error;
1880
+			}
1881
+			goto conn_wait_success;
1882
+		}
1883
+#endif /* TCP_CONNECT_WAIT  && TCP_ASYNC */
1884
+		if (unlikely((c=tcpconn_connect(&dst->to, from, dst->proto,
1885
+										&dst->send_flags))==0)){
1886
+			LOG(L_ERR, "ERROR: tcp_send %s: connect failed\n",
1887
+							su2a(&dst->to, sizeof(dst->to)));
1888
+			return -1;
1889
+		}
1890
+		tcpconn_set_send_flags(c, dst->send_flags);
1891
+		if (likely(c->state==S_CONN_OK))
1892
+			TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
1893
+		atomic_set(&c->refcnt, 2); /* ref. from here and it will also
1894
+									  be added in the tcp_main hash */
1895
+		fd=c->s;
1896
+		c->flags|=F_CONN_FD_CLOSED; /* not yet opened in main */
1897
+		/* ? TODO: it might be faster just to queue the write and
1898
+		 * send to main a CONN_NEW_PENDING_WRITE */
1899
+		
1900
+		/* send the new tcpconn to "tcp main" */
1901
+		response[0]=(long)c;
1902
+		response[1]=CONN_NEW;
1903
+		n=send_fd(unix_tcp_sock, response, sizeof(response), c->s);
1904
+		if (unlikely(n<=0)){
1905
+			LOG(L_ERR, "BUG: tcp_send %s: failed send_fd: %s (%d)\n",
1906
+					su2a(&dst->to, sizeof(dst->to)),
1907
+					strerror(errno), errno);
1908
+			/* we can safely delete it, it's not referenced by anybody */
1909
+			_tcpconn_free(c);
1910
+			n=-1;
1911
+			goto end_no_conn;
1912
+		}
1913
+		/* new connection => send on it directly */
1914
+#ifdef USE_TLS
1915
+		if (unlikely(c->type==PROTO_TLS)) {
1916
+			response[1] = CONN_ERROR; /* in case tls is not loaded */
1917
+			n = tls_do_send(fd, c, buf, len, dst->send_flags,
1918
+							&response[1]);
1919
+		} else
1920
+#endif /* USE_TLS */
1921
+			n = tcpconn_do_send(fd, c, buf, len, dst->send_flags,
1922
+									&response[1], 0);
1923
+		if (unlikely(response[1] != CONN_NOP)) {
1924
+			response[0]=(long)c;
1925
+			if (send_all(unix_tcp_sock, response, sizeof(response)) <= 0) {
1926
+				BUG("tcp_main command %ld sending failed (write):"
1927
+						"%s (%d)\n", response[1], strerror(errno), errno);
1928
+				/* all commands != CONN_NOP returned by tcpconn_do_send()
1929
+				   (CONN_EOF, CONN_ERROR, CONN_QUEUED_WRITE) will auto-dec
1930
+				   refcnt => if sending the command fails we have to
1931
+				   dec. refcnt by hand */
1932
+				tcpconn_chld_put(c); /* deref. it manually */
1933
+				n=-1;
1934
+			}
1935
+			/* here refcnt for c is already decremented => c contents can
1936
+			   no longer be used and refcnt _must_ _not_ be decremented
1937
+			   again on exit */
1938
+			if (unlikely(n < 0 || response[1] == CONN_EOF)) {
1939
+				/* on error or eof, close fd */
1940
+				close(fd);
1941
+			} else if (response[1] == CONN_QUEUED_WRITE) {
1997 1942
 #ifdef TCP_FD_CACHE
1998
-					if (cfg_get(tcp, tcp_cfg, fd_cache)) {
1999
-						tcp_fd_cache_add(c, fd);
2000
-					} else
1943
+				if (cfg_get(tcp, tcp_cfg, fd_cache)) {
1944
+					tcp_fd_cache_add(c, fd);
1945
+				} else
2001 1946
 #endif /* TCP_FD_CACHE */
2002
-						close(fd);
2003
-				} else {
2004
-					BUG("unexpected tcpconn_do_send() return & response:"
2005
-							" %d, %ld\n", n, response[1]);
2006
-				}
2007
-				goto end_no_deref;
1947
+					close(fd);
1948
+			} else {
1949
+				BUG("unexpected tcpconn_do_send() return & response:"
1950
+						" %d, %ld\n", n, response[1]);
2008 1951
 			}
1952
+			goto end_no_deref;
1953
+		}
2009 1954
 #ifdef TCP_FD_CACHE
2010
-			if (cfg_get(tcp, tcp_cfg, fd_cache)) {
2011
-				tcp_fd_cache_add(c, fd);
2012
-			}else
1955
+		if (cfg_get(tcp, tcp_cfg, fd_cache)) {
1956
+			tcp_fd_cache_add(c, fd);
1957
+		}else
2013 1958
 #endif /* TCP_FD_CACHE */
2014
-				close(fd);
2015
-		/* here we can have only commands that _do_ _not_ dec refcnt.
2016
-		   (CONN_EOF, CON_ERROR, CON_QUEUED_WRITE are all treated above) */
2017
-			goto release_c;
2018
-		}
2019
-/* get_fd: */
1959
+			close(fd);
1960
+	/* here we can have only commands that _do_ _not_ dec refcnt.
1961
+	   (CONN_EOF, CON_ERROR, CON_QUEUED_WRITE are all treated above) */
1962
+		goto release_c;
1963
+	} /* if (c==0 or unusable) new connection */
2020 1964
 	/* existing connection, send on it */
2021 1965
 	n = tcpconn_send_put(c, buf, len, dst->send_flags);
2022 1966
 	/* no deref needed (automatically done inside tcpconn_send_put() */
... ...
@@ -2067,7 +2004,7 @@ end_no_conn:
2067 2067
 
2068 2068
 
2069 2069
 
2070
-/** sends on an existing tcpconn.
2070
+/** sends on an existing tcpconn and auto-dec. con. ref counter.
2071 2071
  * As opposed to tcp_send(), this function requires an existing
2072 2072
  * tcp connection.
2073 2073
  * WARNING: the tcp_connection will be de-referenced.
... ...
@@ -2183,7 +2120,13 @@ static int tcpconn_send_put(struct tcp_connection* c, char* buf, unsigned len,
2183 2183
 			DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, fd);
2184 2184
 		}
2185 2185
 	
2186
-	n = tcpconn_do_send(fd, c, buf, len, send_flags, &response[1]);
2186
+#ifdef USE_TLS
2187
+		if (unlikely(c->type==PROTO_TLS)) {
2188
+			response[1] = CONN_ERROR; /* in case tls is not loaded */
2189
+			n = tls_do_send(fd, c, buf, len, send_flags, &response[1]);
2190
+		} else
2191
+#endif
2192
+			n = tcpconn_do_send(fd, c, buf, len, send_flags, &response[1], 0);
2187 2193
 	if (unlikely(response[1] != CONN_NOP)) {
2188 2194
 error:
2189 2195
 		response[0]=(long)c;
... ...
@@ -2239,9 +2182,57 @@ release_c:
2239 2239
 
2240 2240
 
2241 2241
 
2242
+/* unsafe send on a known tcp connection.
2243
+ * Directly send on a known tcp connection with a given fd.
2244
+ * It is assumed that the connection locks are already held.
2245
+ * Side effects: if needed it will send state update commands to
2246
+ *  tcp_main (e.g. CON_EOF, CON_ERROR, CON_QUEUED_WRITE).
2247
+ * @param fd - fd used for sending.
2248
+ * @param c - existing tcp connection pointer (state and flags might be
2249
+ *            changed).
2250
+ * @param buf - data to be sent.
2251
+ * @param len - data length.
2252
+ * @param send_flags
2253
+ * @return <0 on error, number of bytes sent on success.
2254
+ */
2255
+int tcpconn_send_unsafe(int fd, struct tcp_connection *c,
2256
+						char* buf, unsigned len, snd_flags_t send_flags)
2257
+{
2258
+	int n;
2259
+	long response[2];
2260
+	
2261
+	n = tcpconn_do_send(fd, c, buf, len, send_flags, &response[1], 1);
2262
+	if (unlikely(response[1] != CONN_NOP)) {
2263
+		/* all commands != CONN_NOP returned by tcpconn_do_send()
2264
+		   (CONN_EOF, CONN_ERROR, CONN_QUEUED_WRITE) will auto-dec refcnt
2265
+		   => increment it (we don't want the connection to be destroyed
2266
+		   from under us)
2267
+		 */
2268
+		atomic_inc(&c->refcnt);
2269
+		response[0]=(long)c;
2270
+		if (send_all(unix_tcp_sock, response, sizeof(response)) <= 0) {
2271
+			BUG("connection %p command %ld sending failed (write):%s (%d)\n",
2272
+					c, response[1], strerror(errno), errno);
2273
+			/* send failed => deref. it back by hand */
2274
+			tcpconn_chld_put(c); 
2275
+			n=-1;
2276
+		}
2277
+		/* here refcnt for c is already decremented => c contents can no
2278
+		   longer be used and refcnt _must_ _not_ be decremented again
2279
+		   on exit */
2280
+		return n;
2281
+	}
2282
+	return n;
2283
+}
2284
+
2285
+
2286
+
2242 2287
 /** lower level send (connection and fd should be known).
2243 2288
  * It takes care of possible write-queueing, blacklisting a.s.o.
2244 2289
  * It expects a valid tcp connection. It doesn't touch the ref. cnts.
2290
+ * It will also set the connection flags from send_flags (it's better
2291
+ * to do it here, because it's guaranteed to be under lock).
2292
+ * @param fd - fd used for sending.
2245 2293
  * @param c - existing tcp connection pointer (state and flags might be
2246 2294
  *            changed).
2247 2295
  * @param buf - data to be sent.
... ...
@@ -2255,12 +2246,15 @@ release_c:
2255 2255
  *                      CONN_QUEUED_WRITE - new write queue (connection
2256 2256
  *                                 should be watched for write and the wr.
2257 2257
  *                                 queue flushed).
2258
+ * @param locked - if set assume the connection is already locked (call from
2259
+ *                  tls) and do not lock/unlock the connection.
2258 2260
  * @return >=0 on success, < 0 on error && *resp == CON_ERROR.
2259 2261
  *
2260 2262
  */
2261
-static int tcpconn_do_send(int fd, struct tcp_connection* c,
2263
+int tcpconn_do_send(int fd, struct tcp_connection* c,
2262 2264
 							char* buf, unsigned len,
2263
-							snd_flags_t send_flags, long* resp)
2265
+							snd_flags_t send_flags, long* resp,
2266
+							int locked)
2264 2267
 {
2265 2268
 	int  n;
2266 2269
 #ifdef TCP_ASYNC
... ...
@@ -2269,7 +2263,7 @@ static int tcpconn_do_send(int fd, struct tcp_connection* c,
2269 2269
 
2270 2270
 	DBG("tcp_send: sending...\n");
2271 2271
 	*resp = CONN_NOP;
2272
-	lock_get(&c->write_lock);
2272
+	if (likely(!locked)) lock_get(&c->write_lock);
2273 2273
 	/* update connection send flags with the current ones */
2274 2274
 	tcpconn_set_send_flags(c, send_flags);
2275 2275
 #ifdef TCP_ASYNC
... ...
@@ -2280,37 +2274,32 @@ static int tcpconn_do_send(int fd, struct tcp_connection* c,
2280 2280
 #endif /* TCP_CONNECT_WAIT */
2281 2281
 			){
2282 2282
 			if (unlikely(_wbufq_add(c, buf, len)<0)){
2283
-				lock_release(&c->write_lock);
2283
+				if (likely(!locked)) lock_release(&c->write_lock);
2284 2284
 				n=-1;
2285 2285
 				goto error;
2286 2286
 			}
2287
-			lock_release(&c->write_lock);
2287
+			if (likely(!locked)) lock_release(&c->write_lock);
2288 2288
 			n=len;
2289 2289
 			goto end;
2290 2290
 		}
2291 2291
 		n=_tcpconn_write_nb(fd, c, buf, len);
2292 2292
 	}else{
2293 2293
 #endif /* TCP_ASYNC */
2294
-#ifdef USE_TLS
2295
-		if (c->type==PROTO_TLS)
2296
-			n=tls_blocking_write(c, fd, buf, len);
2297
-		else
2298
-#endif
2299 2294
 		/* n=tcp_blocking_write(c, fd, buf, len); */
2300
-			n=tsend_stream(fd, buf, len,
2301
-							TICKS_TO_S(cfg_get(tcp, tcp_cfg, send_timeout)) *
2302
-							1000);
2295
+		n=tsend_stream(fd, buf, len,
2296
+						TICKS_TO_S(cfg_get(tcp, tcp_cfg, send_timeout)) *
2297
+						1000);
2303 2298
 #ifdef TCP_ASYNC
2304 2299
 	}
2305 2300
 #else /* ! TCP_ASYNC */
2306
-	lock_release(&c->write_lock);
2301
+	if (likely(!locked)) lock_release(&c->write_lock);
2307 2302
 #endif /* TCP_ASYNC */
2308 2303
 	
2309 2304
 	DBG("tcp_send: after real write: c= %p n=%d fd=%d\n",c, n, fd);
2310 2305
 	DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
2311 2306
 	if (unlikely(n<(int)len)){
2312 2307
 #ifdef TCP_ASYNC
2313
-		if (cfg_get(tcp, tcp_cfg, async) && 
2308
+		if (cfg_get(tcp, tcp_cfg, async) &&
2314 2309
 				((n>=0) || errno==EAGAIN || errno==EWOULDBLOCK)){
2315 2310
 			enable_write_watch=_wbufq_empty(c);
2316 2311
 			if (n<0) n=0;
... ...
@@ -2320,17 +2309,17 @@ static int tcpconn_do_send(int fd, struct tcp_connection* c,
2320 2320
 				c->state=S_CONN_OK; /* something was written */
2321 2321
 			}
2322 2322
 			if (unlikely(_wbufq_add(c, buf+n, len-n)<0)){
2323
-				lock_release(&c->write_lock);
2323
+				if (likely(!locked)) lock_release(&c->write_lock);
2324 2324
 				n=-1;
2325 2325
 				goto error;
2326 2326
 			}
2327
-			lock_release(&c->write_lock);
2327
+			if (likely(!locked)) lock_release(&c->write_lock);
2328 2328
 			n=len;
2329 2329
 			if (likely(enable_write_watch))
2330 2330
 				*resp=CONN_QUEUED_WRITE;
2331 2331
 			goto end;
2332 2332
 		}else{
2333
-			lock_release(&c->write_lock);
2333
+			if (likely(!locked)) lock_release(&c->write_lock);
2334 2334
 		}
2335 2335
 #endif /* TCP_ASYNC */
2336 2336
 		if (unlikely(c->state==S_CONN_CONNECT)){
... ...
@@ -2390,7 +2379,7 @@ error:
2390 2390
 	}
2391 2391
 	
2392 2392
 #ifdef TCP_ASYNC
2393
-	lock_release(&c->write_lock);
2393
+	if (likely(!locked)) lock_release(&c->write_lock);
2394 2394
 #endif /* TCP_ASYNC */
2395 2395
 	/* in non-async mode here we're either in S_CONN_OK or S_CONN_ACCEPT*/
2396 2396
 	if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
... ...
@@ -2411,6 +2400,121 @@ end:
2411 2411
 
2412 2412
 
2413 2413
 
2414
+/** low level 1st send on a new connection.
2415
+ * It takes care of possible write-queueing, blacklisting a.s.o.
2416
+ * It expects a valid just-opened tcp connection. It doesn't touch the 
2417
+ * ref. counters. It's used only in the async first send case.
2418
+ * @param fd - fd used for sending.
2419
+ * @param c - existing tcp connection pointer (state and flags might be
2420
+ *            changed). The connection must be new (no previous send on it).
2421
+ * @param buf - data to be sent.
2422
+ * @param len - data length.
2423
+ * @param send_flags
2424
+ * @param resp - filled with a fd sending cmd. for tcp_main on success:
2425
+ *                      CONN_NOP - nothing needs to be done (unused right now).
2426
+ *                      CONN_NEW_PENDING_WRITE - new connection, first write
2427
+ *                                 was partially successful (or EAGAIN) and
2428
+ *                                 was queued (connection should be watched
2429
+ *                                 for write and the write queue flushed).
2430
+ *                                 The fd should be sent to tcp_main.
2431
+ *                      CONN_NEW_COMPLETE - new connection, first write
2432
+ *                                 completed successfuly and no data is queued.
2433
+ *                                 The fd should be sent to tcp_main.
2434
+ *                      CONN_EOF - no error, but the connection should be
2435
+ *                                  closed (e.g. SND_F_CON_CLOSE send flag).
2436
+ * @param locked - if set assume the connection is already locked (call from
2437
+ *                  tls) and do not lock/unlock the connection.
2438
+ * @return >=0 on success, < 0 on error (on error *resp is undefined).
2439
+ *
2440
+ */
2441
+int tcpconn_1st_send(int fd, struct tcp_connection* c,
2442
+							char* buf, unsigned len,
2443
+							snd_flags_t send_flags, long* resp,
2444
+							int locked)
2445
+{
2446
+	int n;
2447
+	
2448
+	n=_tcpconn_write_nb(fd, c, buf, len);
2449
+	if (unlikely(n<(int)len)){
2450
+		if ((n>=0) || errno==EAGAIN || errno==EWOULDBLOCK){
2451
+			DBG("pending write on new connection %p "
2452
+				" (%d/%d bytes written)\n", c, n, len);
2453
+			if (unlikely(n<0)) n=0;
2454
+			else{
2455
+				TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
2456
+				c->state=S_CONN_OK; /* partial write => connect()
2457
+												ended */
2458
+			}
2459
+			/* add to the write queue */
2460
+			if (likely(!locked)) lock_get(&c->write_lock);
2461
+				if (unlikely(_wbufq_insert(c, buf+n, len-n)<0)){
2462
+					if (likely(!locked)) lock_release(&c->write_lock);
2463
+					n=-1;
2464
+					LOG(L_ERR, "%s: EAGAIN and"
2465
+							" write queue full or failed for %p\n",
2466
+							su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)), c);
2467
+					goto error;
2468
+				}
2469
+			if (likely(!locked)) lock_release(&c->write_lock);
2470
+			/* send to tcp_main */
2471
+			*resp=CONN_NEW_PENDING_WRITE;
2472
+			n=len;
2473
+			goto end;
2474
+		}
2475
+		/* n < 0 and not EAGAIN => write error */
2476
+		/* if first write failed it's most likely a
2477
+		   connect error */
2478
+		switch(errno){
2479
+			case ENETUNREACH:
2480
+			case EHOSTUNREACH:  /* not posix for send() */
2481
+#ifdef USE_DST_BLACKLIST
2482
+				dst_blacklist_su( BLST_ERR_CONNECT, c->rcv.proto,
2483
+									&c->rcv.src_su, &c->send_flags, 0);
2484
+#endif /* USE_DST_BLACKLIST */
2485
+				TCP_EV_CONNECT_UNREACHABLE(errno, TCP_LADDR(c),
2486
+								TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
2487
+				break;
2488
+			case ECONNREFUSED:
2489
+			case ECONNRESET:
2490
+#ifdef USE_DST_BLACKLIST
2491
+				dst_blacklist_su( BLST_ERR_CONNECT, c->rcv.proto,
2492
+									&c->rcv.src_su, &c->send_flags, 0);
2493
+#endif /* USE_DST_BLACKLIST */
2494
+				TCP_EV_CONNECT_RST(errno, TCP_LADDR(c),
2495
+								TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
2496
+				break;
2497
+			default:
2498
+				TCP_EV_CONNECT_ERR(errno, TCP_LADDR(c),
2499
+								TCP_LPORT(c), TCP_PSU(c), TCP_PROTO(c));
2500
+		}
2501
+		/* error: destroy it directly */
2502
+		TCP_STATS_CONNECT_FAILED();
2503
+		LOG(L_ERR, "%s: connect & send  for %p failed:" " %s (%d)\n",
2504
+					su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)),
2505
+					c, strerror(errno), errno);
2506
+		goto error;
2507
+	}
2508
+	LOG(L_INFO, "quick connect for %p\n", c);
2509
+	TCP_STATS_ESTABLISHED(S_CONN_CONNECT);
2510
+	if (unlikely(send_flags.f & SND_F_CON_CLOSE)){
2511
+		/* close after write =>  EOF => close immediately */
2512
+		c->state=S_CONN_BAD;
2513
+		/* tell our caller that it should drop this*/
2514
+		*resp=CONN_EOF;
2515
+	}else{
2516
+		c->state=S_CONN_OK;
2517
+		/* send to tcp_main */
2518
+		*resp=CONN_NEW_COMPLETE;
2519
+	}
2520
+end:
2521
+	return n; /* >= 0 */
2522
+error:
2523
+	*resp=CONN_ERROR;
2524
+	return -1;
2525
+}
2526
+
2527
+
2528
+
2414 2529
 int tcp_init(struct socket_info* sock_info)
2415 2530
 {
2416 2531
 	union sockaddr_union* addr;
... ...
@@ -2562,7 +2666,6 @@ inline static void tcpconn_close_main_fd(struct tcp_connection* tcpconn)
2562 2562
 	
2563 2563
 	fd=tcpconn->s;
2564 2564
 #ifdef USE_TLS
2565
-	/*FIXME: lock ->writelock ? */
2566 2565
 	if (tcpconn->type==PROTO_TLS)
2567 2566
 		tls_close(tcpconn, fd);
2568 2567
 #endif
... ...
@@ -2609,7 +2712,7 @@ inline static int tcpconn_chld_put(struct tcp_connection* tcpconn)
2609 2609
 
2610 2610
 
2611 2611
 /* simple destroy function (the connection should be already removed
2612
- * from the hashes and the fds should not be watched anymore for IO)
2612
+ * from the hashes. refcnt 0 and the fds should not be watched anymore for IO)
2613 2613
  */
2614 2614
 inline static void tcpconn_destroy(struct tcp_connection* tcpconn)
2615 2615
 {
... ...
@@ -2879,19 +2982,13 @@ inline static void send_fd_queue_run(struct tcp_send_fd_q* q)
2879 2879
  * while holding  c->write_lock). The fd should be non-blocking.
2880 2880
  *  returns number of bytes written on success, -1 on error (and sets errno)
2881 2881
  */
2882
-inline static int _tcpconn_write_nb(int fd, struct tcp_connection* c,
2882
+int _tcpconn_write_nb(int fd, struct tcp_connection* c,
2883 2883
 									char* buf, int len)
2884 2884
 {
2885 2885
 	int n;
2886 2886
 	
2887 2887
 again:
2888
-#ifdef USE_TLS
2889
-	if (unlikely(c->type==PROTO_TLS))
2890
-		/* FIXME: tls_nonblocking_write !! */
2891
-		n=tls_blocking_write(c, fd, buf, len);
2892
-	else
2893
-#endif /* USE_TLS */
2894
-		n=send(fd, buf, len,
2888
+	n=send(fd, buf, len,
2895 2889
 #ifdef HAVE_MSG_NOSIGNAL
2896 2890
 					MSG_NOSIGNAL
2897 2891
 #else
... ...
@@ -42,13 +42,14 @@
42 42
  *              reads (sock. buffer empty) (andrei)
43 43
  * 2009-02-26  direct blacklist support (andrei)
44 44
  * 2009-04-09  tcp ev and tcp stats macros added (andrei)
45
+ * 2010-05-14  split tcp_read() into tcp_read() and tcp_read_data() (andrei)
46
+ * 2010-05-17  new RD_CONN_REPEAT_READ flag, used by the tls hooks (andrei)
45 47
  */
46 48
 
47
-/*!
48
- * \file
49
- * \brief SIP-router core :: 
50
- * \ingroup core
51
- * Module: \ref core
49
+/** tcp readers processes, tcp read and pre-parse msg. functions.
50
+ * @file tcp_read.c
51
+ * @ingroup core
52
+ * Module: @ref core
52 53
  */
53 54
 
54 55
 #ifdef USE_TCP
... ...
@@ -69,6 +70,7 @@
69 69
 
70 70
 #include "dprint.h"
71 71
 #include "tcp_conn.h"
72
+#include "tcp_read.h"
72 73
 #include "tcp_stats.h"
73 74
 #include "tcp_ev.h"
74 75
 #include "pass_fd.h"
... ...
@@ -103,10 +105,6 @@ int is_msg_complete(struct tcp_req* r);
103 103
 
104 104
 #define TCPCONN_TIMEOUT_MIN_RUN  1 /* run the timers each new tick */
105 105
 
106
-#define RD_CONN_SHORT_READ	1
107
-#define RD_CONN_EOF		2
108
-#define RD_CONN_FORCE_EOF	65536
109
-
110 106
 /* types used in io_wait* */
111 107
 enum fd_types { F_NONE, F_TCPMAIN, F_TCPCONN };
112 108
 
... ...
@@ -119,38 +117,43 @@ static struct local_timer tcp_reader_ltimer;
119 119
 static ticks_t tcp_reader_prev_ticks;
120 120
 
121 121
 
122
-/* reads next available bytes
123
- *   c- tcp connection used for reading, tcp_read changes also c->state on
124
- *      EOF and c->req.error on read error
125
- *   * flags - value/result - used to signal a seen or "forced" EOF on the 
122
+/** reads data from an existing tcp connection.
123
+ * Side-effects: blacklisting, sets connection state to S_CONN_OK, tcp stats.
124
+ * @param fd - connection file descriptor
125
+ * @param c - tcp connection structure. c->state might be changed and
126
+ *             receive info might be used for blacklisting.
127
+ * @param buf - buffer where the received data will be stored.
128
+ * @param b_size - buffer size.
129
+ * @param flags - value/result - used to signal a seen or "forced" EOF on the
126 130
  *     connection (when it is known that no more data will come after the 
127
- *     current socket buffer is emptied )=> return/signal EOF on the first 
131
+ *     current socket buffer is emptied )=> return/signal EOF on the first
128 132
  *     short read (=> don't use it on POLLPRI, as OOB data will cause short
129
- *      reads even if there are still remaining bytes in the socket buffer)
130
- * return number of bytes read, 0 on EOF or -1 on error,
133
+ *     reads even if there are still remaining bytes in the socket buffer)
134
+ *     input: RD_CONN_FORCE_EOF  - force EOF after the first successful read
135
+ *                                 (bytes_read >=0 )
136
+ *     output: RD_CONN_SHORT_READ - if the read exhausted all the bytes
137
+ *                                  in the socket read buffer.
138
+ *             RD_CONN_EOF - if EOF detected (0 bytes read) or forced via
139
+ *                           RD_CONN_FORCE_EOF.
140
+ *             RD_CONN_REPEAT_READ - the read should be repeated immediately
141
+ *                                   (used only by the tls code for now).
142
+ *     Note: RD_CONN_SHORT_READ & RD_CONN_EOF must be cleared
143
+ *           before calling this function.
144
+ * @return number of bytes read, 0 on EOF or -1 on error,
131 145
  * on EOF it also sets c->state to S_CONN_EOF.
132 146
  * (to distinguish from reads that would block which could return 0)
133 147
  * RD_CONN_SHORT_READ is also set in *flags for short reads.
134
- * sets also r->error */
135
-int tcp_read(struct tcp_connection *c, int* flags)
148
+ * EOF checking should be done by checking the RD_CONN_EOF flag.
149
+ */
150
+int tcp_read_data(int fd, struct tcp_connection *c,
151
+					char* buf, int b_size, int* flags)
136 152
 {
137
-	int bytes_free, bytes_read;
138
-	struct tcp_req *r;
139
-	int fd;
140
-
141
-	r=&c->req;
142
-	fd=c->fd;
143
-	bytes_free=r->b_size- (int)(r->pos - r->buf);
153
+	int bytes_read;
144 154
 	
145
-	if (bytes_free==0){
146
-		LOG(L_ERR, "ERROR: tcp_read: buffer overrun, dropping\n");
147
-		r->error=TCP_REQ_OVERRUN;
148
-		return -1;
149
-	}
150 155
 again:
151
-	bytes_read=read(fd, r->pos, bytes_free);
152
-
153
-	if (likely(bytes_read!=bytes_free)){
156
+	bytes_read=read(fd, buf, b_size);
157
+	
158
+	if (likely(bytes_read!=b_size)){
154 159
 		if(unlikely(bytes_read==-1)){
155 160
 			if (errno == EWOULDBLOCK || errno == EAGAIN){
156 161
 				bytes_read=0; /* nothing has been read */
... ...
@@ -194,16 +197,14 @@ again:
194 194
 								break;
195 195
 						}
196 196
 				}
197
-				LOG(L_ERR, "ERROR: tcp_read: error reading: %s (%d)\n",
198
-							strerror(errno), errno);
199
-				r->error=TCP_READ_ERROR;
197
+				LOG(L_ERR, "error reading: %s (%d)\n", strerror(errno), errno);
200 198
 				return -1;
201 199
 			}
202 200
 		}else if (unlikely((bytes_read==0) || 
203 201
 					(*flags & RD_CONN_FORCE_EOF))){
204 202
 			c->state=S_CONN_EOF;
205 203
 			*flags|=RD_CONN_EOF;
206
-			DBG("tcp_read: EOF on %p, FD %d\n", c, fd);
204
+			DBG("EOF on %p, FD %d\n", c, fd);
207 205
 		}else{
208 206
 			if (unlikely(c->state==S_CONN_CONNECT || c->state==S_CONN_ACCEPT)){
209 207
 				TCP_STATS_ESTABLISHED(c->state);
... ...
@@ -218,6 +219,44 @@ again:
218 218
 			c->state=S_CONN_OK;
219 219
 		}
220 220
 	}
221
+	return bytes_read;
222
+}
223
+
224
+
225
+
226
+/* reads next available bytes
227
+ *   c- tcp connection used for reading, tcp_read changes also c->state on
228
+ *      EOF and c->req.error on read error
229
+ *   * flags - value/result - used to signal a seen or "forced" EOF on the 
230
+ *     connection (when it is known that no more data will come after the 
231
+ *     current socket buffer is emptied )=> return/signal EOF on the first 
232
+ *     short read (=> don't use it on POLLPRI, as OOB data will cause short
233
+ *      reads even if there are still remaining bytes in the socket buffer)
234
+ * return number of bytes read, 0 on EOF or -1 on error,
235
+ * on EOF it also sets c->state to S_CONN_EOF.
236
+ * (to distinguish from reads that would block which could return 0)
237
+ * RD_CONN_SHORT_READ is also set in *flags for short reads.
238
+ * sets also r->error */
239
+int tcp_read(struct tcp_connection *c, int* flags)
240
+{
241
+	int bytes_free, bytes_read;
242
+	struct tcp_req *r;
243
+	int fd;
244
+
245
+	r=&c->req;
246
+	fd=c->fd;
247
+	bytes_free=r->b_size- (int)(r->pos - r->buf);
248
+	
249
+	if (unlikely(bytes_free==0)){
250
+		LOG(L_ERR, "ERROR: tcp_read: buffer overrun, dropping\n");
251
+		r->error=TCP_REQ_OVERRUN;
252
+		return -1;
253
+	}
254
+	bytes_read = tcp_read_data(fd, c, r->pos, bytes_free, flags);
255
+	if (unlikely(bytes_read < 0)){
256
+		r->error=TCP_READ_ERROR;
257
+		return -1;
258
+	}
221 259
 #ifdef EXTRA_DEBUG
222 260
 	DBG("tcp_read: read %d bytes:\n%.*s\n", bytes_read, bytes_read, r->pos);
223 261
 #endif
... ...
@@ -295,7 +334,7 @@ int tcp_read_headers(struct tcp_connection *c, int* read_flags)
295 295
 	}else{
296 296
 #ifdef USE_TLS
297 297
 		if (unlikely(c->type==PROTO_TLS))
298
-			bytes=tls_read(c); /* FIXME: read_flags support */
298
+			bytes=tls_read(c, read_flags);
299 299
 		else
300 300
 #endif
301 301
 			bytes=tcp_read(c, read_flags);
... ...
@@ -653,16 +692,6 @@ int tcp_read_req(struct tcp_connection* con, int* bytes_read, int* read_flags)
653 653
 		resp=CONN_RELEASE;
654 654
 		s=con->fd;
655 655
 		req=&con->req;
656
-#ifdef USE_TLS
657
-		if (con->type==PROTO_TLS){
658
-			ret=tls_fix_read_conn(con);
659
-			if (unlikely(ret<0)){
660
-				resp=CONN_ERROR;
661
-				goto end_req;
662
-			}else if (unlikely(ret==0))
663
-				goto end_req; /* not enough data */
664
-		}
665
-#endif
666 656
 
667 657
 again:
668 658
 		if (likely(req->error==TCP_REQ_OK)){
... ...
@@ -926,6 +955,9 @@ again:
926 926
 							con, con->id, atomic_get(&con->refcnt));
927 927
 				goto con_error;
928 928
 			}
929
+#ifdef USE_TLS
930
+repeat_1st_read:
931
+#endif /* USE_TLS */
929 932
 			/* if we received the fd there is most likely data waiting to
930 933
 			 * be read => process it first to avoid extra sys calls */
931 934
 			read_flags=((con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)) &&
... ...
@@ -940,6 +972,11 @@ again:
940 940
 				release_tcpconn(con, resp, tcpmain_sock);
941 941
 				break;
942 942
 			}
943
+#ifdef USE_TLS
944
+			/* repeat read if requested (for now only tls might do this) */
945
+			if (unlikely(read_flags & RD_CONN_REPEAT_READ))
946
+				goto repeat_1st_read;
947
+#endif /* USE_TLS */
943 948
 			
944 949
 			/* must be before io_watch_add, io_watch_add might catch some
945 950
 			 * already existing events => might call handle_io and
... ...
@@ -974,8 +1011,11 @@ again:
974 974
 							con, con->id, atomic_get(&con->refcnt));
975 975
 				goto read_error;
976 976
 			}
977
+#ifdef USE_TLS
978
+repeat_read:
979
+#endif /* USE_TLS */
977 980
 #ifdef POLLRDHUP
978
-			read_flags=(((events & POLLRDHUP) | 
981
+			read_flags=(((events & POLLRDHUP) |
979 982
 							(con->flags & (F_CONN_EOF_SEEN|F_CONN_FORCE_EOF)))
980 983
 						&& !(events & POLLPRI))? RD_CONN_FORCE_EOF: 0;
981 984
 #else /* POLLRDHUP */
... ...
@@ -999,11 +1039,15 @@ read_error:
999 999
 					con->state=S_CONN_BAD;
1000 1000
 				release_tcpconn(con, resp, tcpmain_sock);
1001 1001
 			}else{
1002
+#ifdef USE_TLS
1003
+				if (unlikely(read_flags & RD_CONN_REPEAT_READ))
1004
+						goto repeat_read;
1005
+#endif /* USE_TLS */
1002 1006
 				/* update timeout */
1003 1007
 				con->timeout=get_ticks_raw()+S_TO_TICKS(TCP_CHILD_TIMEOUT);
1004 1008
 				/* ret= 0 (read the whole socket buffer) if short read & 
1005 1009
 				 *  !POLLPRI,  bytes read otherwise */
1006
-				ret&=(((read_flags & RD_CONN_SHORT_READ) && 
1010
+				ret&=(((read_flags & RD_CONN_SHORT_READ) &&
1007 1011
 						!(events & POLLPRI)) - 1);
1008 1012
 			}
1009 1013
 			break;
1010 1014
new file mode 100644
... ...
@@ -0,0 +1,46 @@
0
+/* 
1
+ * $Id$
2
+ * 
3
+ * Copyright (C) 2010 iptelorg GmbH
4
+ *
5
+ * Permission to use, copy, modify, and distribute this software for any
6
+ * purpose with or without fee is hereby granted, provided that the above
7
+ * copyright notice and this permission notice appear in all copies.
8
+ *
9
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ */
17
+/** tcp internal read functions.
18
+ * @file tcp_read.h
19
+ * @ingroup: core
20
+ * Module: @ref core
21
+ */
22
+/*
23
+ * History:
24
+ * --------
25
+ *  2010-05-18  initial version (andrei)
26
+*/
27
+
28
+#ifndef __tcp_read_h
29
+#define __tcp_read_h
30
+
31
+#include  "tcp_conn.h"
32
+
33
+#define RD_CONN_SHORT_READ		1
34
+#define RD_CONN_EOF				2
35
+#define RD_CONN_REPEAT_READ		4 /* read should be repeated (more data)
36
+								   (used so far only by tls) */
37
+#define RD_CONN_FORCE_EOF		65536
38
+
39
+int tcp_read_data(int fd, struct tcp_connection *c,
40
+					char* buf, int b_size, int* flags);
41
+
42
+
43
+#endif /*__tcp_read_h*/
44
+
45
+/* vi: set ts=4 sw=4 tw=79:ai:cindent: */
... ...
@@ -21,6 +21,7 @@
21 21
  * History:
22 22
  * --------
23 23
  *  2007-02-09  created by andrei
24
+ *  2010-05-14  new hook interface (better suited for async. tcp) (andrei)
24 25
  */
25 26
 
26 27
 /**
... ...
@@ -50,21 +51,18 @@
50 50
 
51 51
 
52 52
 struct tls_hooks{
53
-	int  (*read)(struct tcp_connection* c);
54
-	int (*blocking_write)(struct tcp_connection* c, int fd, const char* buf,
55
-							unsigned int len);
53
+	int  (*read)(struct tcp_connection* c, int* flags);
54
+	/* send using tls on a tcp connection */
55
+	int (*do_send)(int fd, struct tcp_connection* c, const char* buf,
56
+							unsigned int len, snd_flags_t send_flags,
57
+							long* resp);
58
+	/* 1st send using tls on a new async. tcp connection */
59
+	int (*fst_send)(int fd, struct tcp_connection* c, const char* buf,
60
+							unsigned int len, snd_flags_t send_flags,
61
+							long* resp);
56 62
 	int  (*on_tcpconn_init)(struct tcp_connection *c, int sock);
57 63
 	void (*tcpconn_clean)(struct tcp_connection* c);
58 64
 	void (*tcpconn_close)(struct tcp_connection*c , int fd);
59
-	/* checks if a tls connection is fully established before a read, and if 
60
-	 * not it runs tls_accept() or tls_connect() as needed
61
-	 * (tls_accept and tls_connect are deferred to the "reader" process for
62
-	 *  performance reasons)
63
-	 * returns 1 if the read can continue, 0 if the connection is not yet
64
-	 * ready for the read and fix_read_con() should be attempted at a latter
65
-	 * time and <0 on error.
66
-	 */
67
-	int (*fix_read_con)(struct tcp_connection* c);
68 65
 	
69 66
 	/* per listening socket init, called on ser startup (after modules,
70 67
 	 *  process table, init() and udp socket initialization)*/
... ...
@@ -100,11 +98,12 @@ extern struct tls_hooks tls_hook;
100 100
 
101 101
 #define tls_tcpconn_init(c, s)	tls_hook_call(on_tcpconn_init, 0, (c), (s))
102 102
 #define tls_tcpconn_clean(c)	tls_hook_call_v(tcpconn_clean, (c))
103
-#define tls_blocking_write(c, fd, buf, len) \
104
-	tls_hook_call(blocking_write, -1, (c), (fd), (buf), (len))
103
+#define tls_do_send(fd, c, buf, len, send_flags, resp) \
104
+	tls_hook_call(do_send, -1, (fd), (c), (buf), (len), (send_flags), (resp))
105
+#define tls_1st_send(fd, c, buf, len, send_flags, resp) \
106
+	tls_hook_call(fst_send, -1, (fd), (c), (buf), (len), (send_flags), (resp))
105 107
 #define tls_close(conn, fd)		tls_hook_call_v(tcpconn_close, (conn), (fd))
106
-#define tls_read(c)				tls_hook_call(read, -1, (c))
107
-#define tls_fix_read_conn(c)	tls_hook_call(fix_read_con, -1, (c))
108
+#define tls_read(c, flags)				tls_hook_call(read, -1, (c), (flags))
108 109
 
109 110
 int register_tls_hooks(struct tls_hooks* h);
110 111