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