- 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.
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 |
|