Non critical:
- BUG message for CONN_ERROR (it's not a bug)
- find_tls_si will be called now for tls connection (tcp_connect), it will
probably fix SUBST_RCV_* proto (tcp set also for tls). Very unlikely to
hit this (but possible: e.g. RR on tls to something and a request is rr'ed
which is received on a tls connection opened _by_ _us_, very unlikely without
the new tcp aliasing ).
Critical:
- non atomic unix sock read
- tcp refcnt non-atomic dec
- tls lock read & writes on the same connection are now mutually exclusive
to avoid stealing the fds
... | ... |
@@ -43,7 +43,7 @@ export makefile_defs |
43 | 43 |
VERSION = 0 |
44 | 44 |
PATCHLEVEL = 8 |
45 | 45 |
SUBLEVEL = 12 |
46 |
-EXTRAVERSION = testing-20 |
|
46 |
+EXTRAVERSION = testing-22 |
|
47 | 47 |
|
48 | 48 |
RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) |
49 | 49 |
OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]") |
... | ... |
@@ -29,6 +29,8 @@ |
29 | 29 |
* -------- |
30 | 30 |
* 2002-11-29 created by andrei |
31 | 31 |
* 2003-02-20 added solaris support (! HAVE_MSGHDR_MSG_CONTROL) (andrei) |
32 |
+ * 2003-11-03 added send_all, recv_all and updated send/get_fd |
|
33 |
+ * to handle signals (andrei) |
|
32 | 34 |
*/ |
33 | 35 |
|
34 | 36 |
#ifdef USE_TCP |
... | ... |
@@ -37,10 +39,55 @@ |
37 | 39 |
#include <sys/socket.h> |
38 | 40 |
#include <sys/uio.h> |
39 | 41 |
#include <stdlib.h> /* for NULL definition on openbsd */ |
42 |
+#include <errno.h> |
|
43 |
+#include <string.h> |
|
40 | 44 |
|
41 | 45 |
#include "dprint.h" |
42 | 46 |
|
43 | 47 |
|
48 |
+ |
|
49 |
+/* receive all the data or returns error (handles EINTR etc.) |
|
50 |
+ * returns: bytes read or error (<0) |
|
51 |
+ * can return < data_len if EOF */ |
|
52 |
+int recv_all(int socket, void* data, int data_len) |
|
53 |
+{ |
|
54 |
+ int b_read; |
|
55 |
+ int n; |
|
56 |
+ |
|
57 |
+ b_read=0; |
|
58 |
+ do{ |
|
59 |
+ n=recv(socket, data+b_read, data_len-b_read, MSG_WAITALL); |
|
60 |
+ if (n<0){ |
|
61 |
+ /* error */ |
|
62 |
+ if (errno==EINTR) continue; /* signal, try again */ |
|
63 |
+ LOG(L_CRIT, "ERROR: recv_all: recv on %d failed: %s\n", |
|
64 |
+ socket, strerror(errno)); |
|
65 |
+ return n; |
|
66 |
+ } |
|
67 |
+ b_read+=n; |
|
68 |
+ }while( (b_read!=data_len) && (n)); |
|
69 |
+ return b_read; |
|
70 |
+} |
|
71 |
+ |
|
72 |
+ |
|
73 |
+/* sends all data (takes care of signals) |
|
74 |
+ * returns number of bytes sent or < 0 for an error */ |
|
75 |
+int send_all(int socket, void* data, int data_len) |
|
76 |
+{ |
|
77 |
+ int n; |
|
78 |
+ |
|
79 |
+again: |
|
80 |
+ n=send(socket, data, data_len, 0); |
|
81 |
+ if (n<0){ |
|
82 |
+ /* error */ |
|
83 |
+ if (errno==EINTR) goto again; /* signal, try again */ |
|
84 |
+ LOG(L_CRIT, "ERROR: send_all: send on %d failed: %s\n", |
|
85 |
+ socket, strerror(errno)); |
|
86 |
+ } |
|
87 |
+ return n; |
|
88 |
+} |
|
89 |
+ |
|
90 |
+ |
|
44 | 91 |
/* at least 1 byte must be sent! */ |
45 | 92 |
int send_fd(int unix_socket, void* data, int data_len, int fd) |
46 | 93 |
{ |
... | ... |
@@ -76,8 +123,13 @@ int send_fd(int unix_socket, void* data, int data_len, int fd) |
76 | 123 |
msg.msg_iov=iov; |
77 | 124 |
msg.msg_iovlen=1; |
78 | 125 |
|
79 |
- |
|
126 |
+again: |
|
80 | 127 |
ret=sendmsg(unix_socket, &msg, 0); |
128 |
+ if (ret<0){ |
|
129 |
+ if (errno==EINTR) goto again; |
|
130 |
+ LOG(L_CRIT, "ERROR: send_fd: sendmsg failed on %d: %s\n", |
|
131 |
+ unix_socket, strerror(errno)); |
|
132 |
+ } |
|
81 | 133 |
|
82 | 134 |
return ret; |
83 | 135 |
} |
... | ... |
@@ -90,6 +142,7 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd) |
90 | 142 |
struct iovec iov[1]; |
91 | 143 |
int new_fd; |
92 | 144 |
int ret; |
145 |
+ int n; |
|
93 | 146 |
#ifdef HAVE_MSGHDR_MSG_CONTROL |
94 | 147 |
struct cmsghdr* cmsg; |
95 | 148 |
union{ |
... | ... |
@@ -112,26 +165,47 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd) |
112 | 165 |
msg.msg_iov=iov; |
113 | 166 |
msg.msg_iovlen=1; |
114 | 167 |
|
115 |
- ret=recvmsg(unix_socket, &msg, 0); |
|
116 |
- if (ret<=0) goto error; |
|
168 |
+again: |
|
169 |
+ ret=recvmsg(unix_socket, &msg, MSG_WAITALL); |
|
170 |
+ if (ret<0){ |
|
171 |
+ if (errno==EINTR) goto again; |
|
172 |
+ LOG(L_CRIT, "ERROR: receive_fd: recvmsg on %d failed: %s\n", |
|
173 |
+ unix_socket, strerror(errno)); |
|
174 |
+ goto error; |
|
175 |
+ } |
|
176 |
+ if (ret==0){ |
|
177 |
+ /* EOF */ |
|
178 |
+ LOG(L_CRIT, "ERROR: receive_fd: EOF on %d\n", unix_socket); |
|
179 |
+ goto error; |
|
180 |
+ } |
|
181 |
+ if (ret<data_len){ |
|
182 |
+ LOG(L_WARN, "WARNING: receive_fd: too few bytes read (%d from %d)" |
|
183 |
+ "trying to fix...\n", ret, data_len); |
|
184 |
+ n=recv_all(unix_socket, (char*)data+ret, data_len-ret); |
|
185 |
+ if (n>=0) ret+=n; |
|
186 |
+ else{ |
|
187 |
+ ret=n; |
|
188 |
+ goto error; |
|
189 |
+ } |
|
190 |
+ } |
|
117 | 191 |
|
118 | 192 |
#ifdef HAVE_MSGHDR_MSG_CONTROL |
119 | 193 |
cmsg=CMSG_FIRSTHDR(&msg); |
120 | 194 |
if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){ |
121 | 195 |
if (cmsg->cmsg_type!= SCM_RIGHTS){ |
122 |
- LOG(L_ERR, "receive_fd: msg control type != SCM_RIGHTS\n"); |
|
196 |
+ LOG(L_ERR, "ERROR: receive_fd: msg control type != SCM_RIGHTS\n"); |
|
123 | 197 |
ret=-1; |
124 | 198 |
goto error; |
125 | 199 |
} |
126 | 200 |
if (cmsg->cmsg_level!= SOL_SOCKET){ |
127 |
- LOG(L_ERR, "receive_fd: msg level != SOL_SOCKET\n"); |
|
201 |
+ LOG(L_ERR, "ERROR: receive_fd: msg level != SOL_SOCKET\n"); |
|
128 | 202 |
ret=-1; |
129 | 203 |
goto error; |
130 | 204 |
} |
131 | 205 |
*fd=*((int*) CMSG_DATA(cmsg)); |
132 | 206 |
}else{ |
133 |
- LOG(L_ERR, "receive_fd: no descriptor passed, cmsg=%p, len=%d\n", |
|
134 |
- cmsg, cmsg->cmsg_len); |
|
207 |
+ LOG(L_ERR, "ERROR: receive_fd: no descriptor passed, cmsg=%p," |
|
208 |
+ "len=%d\n", cmsg, cmsg->cmsg_len); |
|
135 | 209 |
*fd=-1; |
136 | 210 |
/* it's not really an error */ |
137 | 211 |
} |
... | ... |
@@ -139,8 +213,8 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd) |
139 | 213 |
if (msg.msg_accrightslen==sizeof(int)){ |
140 | 214 |
*fd=new_fd; |
141 | 215 |
}else{ |
142 |
- LOG(L_ERR, "receive_fd: no descriptor passed, accrightslen=%d\n", |
|
143 |
- msg.msg_accrightslen); |
|
216 |
+ LOG(L_ERR, "ERROR: receive_fd: no descriptor passed," |
|
217 |
+ " accrightslen=%d\n", msg.msg_accrightslen); |
|
144 | 218 |
*fd=-1; |
145 | 219 |
} |
146 | 220 |
#endif |
... | ... |
@@ -148,5 +222,4 @@ int receive_fd(int unix_socket, void* data, int data_len, int* fd) |
148 | 222 |
error: |
149 | 223 |
return ret; |
150 | 224 |
} |
151 |
- |
|
152 | 225 |
#endif |
... | ... |
@@ -32,6 +32,8 @@ |
32 | 32 |
int send_fd(int unix_socket, void* data, int data_len, int fd); |
33 | 33 |
int receive_fd(int unix_socket, void* data, int data_len, int* fd); |
34 | 34 |
|
35 |
+int recv_all(int socket, void* data, int data_len); |
|
36 |
+int send_all(int socket, void* data, int data_len); |
|
35 | 37 |
|
36 | 38 |
|
37 | 39 |
#endif |
... | ... |
@@ -42,8 +42,8 @@ |
42 | 42 |
* 2003-06-30 moved tcp new connect checking & handling to |
43 | 43 |
* handle_new_connect (andrei) |
44 | 44 |
* 2003-07-09 tls_close called before closing the tcp connection (andrei) |
45 |
- * 2003-10-24 converted to the new socket_info lists (andrei) |
|
46 |
- * 2003-10-27 tcp port aliases support added (andrei) |
|
45 |
+ * 2003-11-04 always lock before manipulating refcnt; sendchild |
|
46 |
+ * does not inc refcnt by itself anymore (andrei) |
|
47 | 47 |
*/ |
48 | 48 |
|
49 | 49 |
|
... | ... |
@@ -106,10 +106,9 @@ struct tcp_child{ |
106 | 106 |
}; |
107 | 107 |
|
108 | 108 |
|
109 |
-int tcp_accept_aliases=0; /* by default don't accept aliases */ |
|
110 | 109 |
|
111 |
-/* connection hash table (after ip&port) , includes also aliases */ |
|
112 |
-struct tcp_conn_alias** tcpconn_aliases_hash=0; |
|
110 |
+/* connection hash table (after ip&port) */ |
|
111 |
+struct tcp_connection** tcpconn_addr_hash=0; |
|
113 | 112 |
/* connection hash table (after connection id) */ |
114 | 113 |
struct tcp_connection** tcpconn_id_hash=0; |
115 | 114 |
gen_lock_t* tcpconn_lock=0; |
... | ... |
@@ -134,7 +133,6 @@ struct tcp_connection* tcpconn_new(int sock, union sockaddr_union* su, |
134 | 133 |
LOG(L_ERR, "ERROR: tcpconn_new: mem. allocation failure\n"); |
135 | 134 |
goto error; |
136 | 135 |
} |
137 |
- memset(c, 0, sizeof(struct tcp_connection)); /* zero init */ |
|
138 | 136 |
c->s=sock; |
139 | 137 |
c->fd=-1; /* not initialized */ |
140 | 138 |
if (lock_init(&c->write_lock)==0){ |
... | ... |
@@ -185,14 +183,14 @@ error: |
185 | 183 |
|
186 | 184 |
struct socket_info* find_tcp_si(union sockaddr_union* s) |
187 | 185 |
{ |
186 |
+ int r; |
|
188 | 187 |
struct ip_addr ip; |
189 |
- struct socket_info* si; |
|
190 | 188 |
|
191 | 189 |
su2ip_addr(&ip, s); |
192 |
- for (si=tcp_listen; si; si=si->next) |
|
193 |
- if (ip_addr_cmp(&ip, &si->address)){ |
|
190 |
+ for (r=0; r<sock_no; r++) |
|
191 |
+ if (ip_addr_cmp(&ip, &tcp_info[r].address)){ |
|
194 | 192 |
/* found it, we use first match */ |
195 |
- return si; |
|
193 |
+ return &tcp_info[r]; |
|
196 | 194 |
} |
197 | 195 |
return 0; /* no match */ |
198 | 196 |
} |
... | ... |
@@ -242,7 +240,13 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server, int type) |
242 | 240 |
strerror(errno), errno); |
243 | 241 |
si=0; /* try to go on */ |
244 | 242 |
} |
245 |
- si=find_tcp_si(&my_name); |
|
243 |
+#ifdef USE_TLS |
|
244 |
+ if (type==PROTO_TLS) |
|
245 |
+ si=find_tls_si(&my_name); |
|
246 |
+ else |
|
247 |
+#endif |
|
248 |
+ si=find_tcp_si(&my_name); |
|
249 |
+ |
|
246 | 250 |
if (si==0){ |
247 | 251 |
LOG(L_ERR, "ERROR: tcp_connect: could not find coresponding" |
248 | 252 |
" listening socket, using default...\n"); |
... | ... |
@@ -266,20 +270,14 @@ struct tcp_connection* tcpconn_add(struct tcp_connection *c) |
266 | 270 |
if (c){ |
267 | 271 |
TCPCONN_LOCK; |
268 | 272 |
/* add it at the begining of the list*/ |
273 |
+ hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port); |
|
274 |
+ c->addr_hash=hash; |
|
275 |
+ tcpconn_listadd(tcpconn_addr_hash[hash], c, next, prev); |
|
269 | 276 |
hash=tcp_id_hash(c->id); |
270 | 277 |
c->id_hash=hash; |
271 | 278 |
tcpconn_listadd(tcpconn_id_hash[hash], c, id_next, id_prev); |
272 |
- |
|
273 |
- hash=tcp_addr_hash(&c->rcv.src_ip, c->rcv.src_port); |
|
274 |
- /* set the first alias */ |
|
275 |
- c->con_aliases[0].port=c->rcv.src_port; |
|
276 |
- c->con_aliases[0].hash=hash; |
|
277 |
- c->con_aliases[0].parent=c; |
|
278 |
- tcpconn_listadd(tcpconn_aliases_hash[hash], &c->con_aliases[0], |
|
279 |
- next, prev); |
|
280 |
- c->aliases++; |
|
281 | 279 |
TCPCONN_UNLOCK; |
282 |
- DBG("tcpconn_add: hashes: %d, %d\n", hash, c->id_hash); |
|
280 |
+ DBG("tcpconn_add: hashes: %d, %d\n", c->addr_hash, c->id_hash); |
|
283 | 281 |
return c; |
284 | 282 |
}else{ |
285 | 283 |
LOG(L_CRIT, "tcpconn_add: BUG: null connection pointer\n"); |
... | ... |
@@ -291,12 +289,8 @@ struct tcp_connection* tcpconn_add(struct tcp_connection *c) |
291 | 289 |
/* unsafe tcpconn_rm version (nolocks) */ |
292 | 290 |
void _tcpconn_rm(struct tcp_connection* c) |
293 | 291 |
{ |
294 |
- int r; |
|
292 |
+ tcpconn_listrm(tcpconn_addr_hash[c->addr_hash], c, next, prev); |
|
295 | 293 |
tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev); |
296 |
- /* remove all the aliases */ |
|
297 |
- for (r=0; r<c->aliases; r++) |
|
298 |
- tcpconn_listrm(tcpconn_aliases_hash[c->con_aliases[r].hash], |
|
299 |
- &c->con_aliases[r], next, prev); |
|
300 | 294 |
lock_destroy(&c->write_lock); |
301 | 295 |
#ifdef USE_TLS |
302 | 296 |
if (c->type==PROTO_TLS) tls_tcpconn_clean(c); |
... | ... |
@@ -308,13 +302,9 @@ void _tcpconn_rm(struct tcp_connection* c) |
308 | 302 |
|
309 | 303 |
void tcpconn_rm(struct tcp_connection* c) |
310 | 304 |
{ |
311 |
- int r; |
|
312 | 305 |
TCPCONN_LOCK; |
306 |
+ tcpconn_listrm(tcpconn_addr_hash[c->addr_hash], c, next, prev); |
|
313 | 307 |
tcpconn_listrm(tcpconn_id_hash[c->id_hash], c, id_next, id_prev); |
314 |
- /* remove all the aliases */ |
|
315 |
- for (r=0; r<c->aliases; r++) |
|
316 |
- tcpconn_listrm(tcpconn_aliases_hash[c->con_aliases[r].hash], |
|
317 |
- &c->con_aliases[r], next, prev); |
|
318 | 308 |
TCPCONN_UNLOCK; |
319 | 309 |
lock_destroy(&c->write_lock); |
320 | 310 |
#ifdef USE_TLS |
... | ... |
@@ -331,12 +321,11 @@ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port) |
331 | 321 |
{ |
332 | 322 |
|
333 | 323 |
struct tcp_connection *c; |
334 |
- struct tcp_conn_alias* a; |
|
335 | 324 |
unsigned hash; |
336 | 325 |
|
337 | 326 |
#ifdef EXTRA_DEBUG |
338 | 327 |
DBG("tcpconn_find: %d port %d\n",id, port); |
339 |
- if (ip) print_ip("tcpconn_find: ip ", ip, "\n"); |
|
328 |
+ print_ip("tcpconn_find: ip ", ip, "\n"); |
|
340 | 329 |
#endif |
341 | 330 |
if (id){ |
342 | 331 |
hash=tcp_id_hash(id); |
... | ... |
@@ -349,15 +338,14 @@ struct tcp_connection* _tcpconn_find(int id, struct ip_addr* ip, int port) |
349 | 338 |
} |
350 | 339 |
}else if (ip){ |
351 | 340 |
hash=tcp_addr_hash(ip, port); |
352 |
- for (a=tcpconn_aliases_hash[hash]; a; a=a->next){ |
|
341 |
+ for (c=tcpconn_addr_hash[hash]; c; c=c->next){ |
|
353 | 342 |
#ifdef EXTRA_DEBUG |
354 |
- DBG("a=%p, c=%p, c->id=%d, alias port= %d port=%d\n", a, a->parent, |
|
355 |
- a->parent->id, a->port, a->parent->rcv.src_port); |
|
356 |
- print_ip("ip=",&a->parent->rcv.src_ip,"\n"); |
|
343 |
+ DBG("c=%p, c->id=%d, port=%d\n",c, c->id, c->rcv.src_port); |
|
344 |
+ print_ip("ip=",&c->rcv.src_ip,"\n"); |
|
357 | 345 |
#endif |
358 |
- if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) && |
|
359 |
- (ip_addr_cmp(ip, &a->parent->rcv.src_ip)) ) |
|
360 |
- return a->parent; |
|
346 |
+ if ( (c->state!=S_CONN_BAD) && (port==c->rcv.src_port) && |
|
347 |
+ (ip_addr_cmp(ip, &c->rcv.src_ip)) ) |
|
348 |
+ return c; |
|
361 | 349 |
} |
362 | 350 |
} |
363 | 351 |
return 0; |
... | ... |
@@ -382,70 +370,20 @@ struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port, |
382 | 370 |
|
383 | 371 |
|
384 | 372 |
|
385 |
-/* add port as an alias for the "id" connection |
|
386 |
- * returns 0 on success,-1 on failure */ |
|
387 |
-int tcpconn_add_alias(int id, int port, int proto) |
|
373 |
+void tcpconn_ref(struct tcp_connection* c) |
|
388 | 374 |
{ |
389 |
- struct tcp_connection* c; |
|
390 |
- unsigned hash; |
|
391 |
- struct tcp_conn_alias* a; |
|
392 |
- |
|
393 |
- a=0; |
|
394 |
- /* fix the port */ |
|
395 |
- port=port?port:((proto==PROTO_TLS)?SIPS_PORT:SIP_PORT); |
|
396 | 375 |
TCPCONN_LOCK; |
397 |
- /* check if alias already exists */ |
|
398 |
- c=_tcpconn_find(id, 0, 0); |
|
399 |
- if (c){ |
|
400 |
- hash=tcp_addr_hash(&c->rcv.src_ip, port); |
|
401 |
- /* search the aliases for an already existing one */ |
|
402 |
- for (a=tcpconn_aliases_hash[hash]; a; a=a->next){ |
|
403 |
- if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) && |
|
404 |
- (ip_addr_cmp(&c->rcv.src_ip, &a->parent->rcv.src_ip)) ){ |
|
405 |
- /* found */ |
|
406 |
- if (a->parent!=c) goto error_sec; |
|
407 |
- else goto ok; |
|
408 |
- } |
|
409 |
- } |
|
410 |
- if (c->aliases>=TCP_CON_MAX_ALIASES) goto error_aliases; |
|
411 |
- c->con_aliases[c->aliases].parent=c; |
|
412 |
- c->con_aliases[c->aliases].port=port; |
|
413 |
- c->con_aliases[c->aliases].hash=hash; |
|
414 |
- tcpconn_listadd(tcpconn_aliases_hash[hash], |
|
415 |
- &c->con_aliases[c->aliases], next, prev); |
|
416 |
- c->aliases++; |
|
417 |
- }else goto error_not_found; |
|
418 |
-ok: |
|
419 |
- TCPCONN_UNLOCK; |
|
420 |
-#ifdef EXTRA_DEBUG |
|
421 |
- if (a) DBG("tcpconn_add_alias: alias already present\n"); |
|
422 |
- else DBG("tcpconn_add_alias: alias port %d for hash %d, id %d\n", |
|
423 |
- port, hash, c->id); |
|
424 |
-#endif |
|
425 |
- return 0; |
|
426 |
-error_aliases: |
|
427 |
- TCPCONN_UNLOCK; |
|
428 |
- LOG(L_ERR, "ERROR: tcpconn_add_alias: too many aliases for connection %p" |
|
429 |
- " (%d)\n", c, c->id); |
|
430 |
- return -1; |
|
431 |
-error_not_found: |
|
376 |
+ c->refcnt++; /* FIXME: atomic_dec */ |
|
432 | 377 |
TCPCONN_UNLOCK; |
433 |
- LOG(L_ERR, "ERROR: tcpconn_add_alias: no connection found for id %d\n",id); |
|
434 |
- return -1; |
|
435 |
-error_sec: |
|
436 |
- TCPCONN_UNLOCK; |
|
437 |
- LOG(L_ERR, "ERROR: tcpconn_add_alias: possible port hijack attemp\n"); |
|
438 |
- LOG(L_ERR, "ERROR: tcpconn_add_alias: alias already present and points" |
|
439 |
- " to another connection (%d : %d and %d : %d)\n", |
|
440 |
- a->parent->id, port, c->id, port); |
|
441 |
- return -1; |
|
442 | 378 |
} |
443 | 379 |
|
444 | 380 |
|
445 | 381 |
|
446 | 382 |
void tcpconn_put(struct tcp_connection* c) |
447 | 383 |
{ |
384 |
+ TCPCONN_LOCK; |
|
448 | 385 |
c->refcnt--; /* FIXME: atomic_dec */ |
386 |
+ TCPCONN_UNLOCK; |
|
449 | 387 |
} |
450 | 388 |
|
451 | 389 |
|
... | ... |
@@ -494,22 +432,25 @@ no_id: |
494 | 432 |
LOG(L_ERR, "ERROR: tcp_send: connect failed\n"); |
495 | 433 |
return -1; |
496 | 434 |
} |
497 |
- c->refcnt++; |
|
435 |
+ c->refcnt++; /* safe to do it w/o locking, it's not yet |
|
436 |
+ available to the rest of the world */ |
|
498 | 437 |
fd=c->s; |
499 | 438 |
|
500 | 439 |
/* send the new tcpconn to "tcp main" */ |
501 | 440 |
response[0]=(long)c; |
502 | 441 |
response[1]=CONN_NEW; |
503 |
- n=write(unix_tcp_sock, response, sizeof(response)); |
|
504 |
- if (n<0){ |
|
442 |
+ n=send_all(unix_tcp_sock, response, sizeof(response)); |
|
443 |
+ if (n<=0){ |
|
505 | 444 |
LOG(L_ERR, "BUG: tcp_send: failed write: %s (%d)\n", |
506 | 445 |
strerror(errno), errno); |
446 |
+ n=-1; |
|
507 | 447 |
goto end; |
508 | 448 |
} |
509 | 449 |
n=send_fd(unix_tcp_sock, &c, sizeof(c), c->s); |
510 |
- if (n<0){ |
|
450 |
+ if (n<=0){ |
|
511 | 451 |
LOG(L_ERR, "BUG: tcp_send: failed send_fd: %s (%d)\n", |
512 | 452 |
strerror(errno), errno); |
453 |
+ n=-1; |
|
513 | 454 |
goto end; |
514 | 455 |
} |
515 | 456 |
goto send_it; |
... | ... |
@@ -517,21 +458,23 @@ no_id: |
517 | 458 |
get_fd: |
518 | 459 |
/* todo: see if this is not the same process holding |
519 | 460 |
* c and if so send directly on c->fd */ |
520 |
- DBG("tcp_send: tcp connection found, acquiring fd\n"); |
|
461 |
+ DBG("tcp_send: tcp connection found (%p), acquiring fd\n", c); |
|
521 | 462 |
/* get the fd */ |
522 | 463 |
response[0]=(long)c; |
523 | 464 |
response[1]=CONN_GET_FD; |
524 |
- n=write(unix_tcp_sock, response, sizeof(response)); |
|
525 |
- if (n<0){ |
|
465 |
+ n=send_all(unix_tcp_sock, response, sizeof(response)); |
|
466 |
+ if (n<=0){ |
|
526 | 467 |
LOG(L_ERR, "BUG: tcp_send: failed to get fd(write):%s (%d)\n", |
527 | 468 |
strerror(errno), errno); |
469 |
+ n=-1; |
|
528 | 470 |
goto release_c; |
529 | 471 |
} |
530 | 472 |
DBG("tcp_send, c= %p, n=%d\n", c, n); |
531 | 473 |
n=receive_fd(unix_tcp_sock, &c, sizeof(c), &fd); |
532 |
- if (n<0){ |
|
474 |
+ if (n<=0){ |
|
533 | 475 |
LOG(L_ERR, "BUG: tcp_send: failed to get fd(receive_fd):" |
534 | 476 |
" %s (%d)\n", strerror(errno), errno); |
477 |
+ n=-1; |
|
535 | 478 |
goto release_c; |
536 | 479 |
} |
537 | 480 |
DBG("tcp_send: after receive_fd: c= %p n=%d fd=%d\n",c, n, fd); |
... | ... |
@@ -567,11 +510,12 @@ send_it: |
567 | 510 |
/* tell "main" it should drop this (optional it will t/o anyway?)*/ |
568 | 511 |
response[0]=(long)c; |
569 | 512 |
response[1]=CONN_ERROR; |
570 |
- n=write(unix_tcp_sock, response, sizeof(response)); |
|
571 |
- /* CONN_ERROR wil auto-dec refcnt => we must not call tcpconn_put !!*/ |
|
572 |
- if (n<0){ |
|
513 |
+ n=send_all(unix_tcp_sock, response, sizeof(response)); |
|
514 |
+ /* CONN_ERROR will auto-dec refcnt => we must not call tcpconn_put !!*/ |
|
515 |
+ if (n<=0){ |
|
573 | 516 |
LOG(L_ERR, "BUG: tcp_send: error return failed (write):%s (%d)\n", |
574 | 517 |
strerror(errno), errno); |
518 |
+ n=-1; |
|
575 | 519 |
} |
576 | 520 |
close(fd); |
577 | 521 |
return n; /* error return, no tcpconn_put */ |
... | ... |
@@ -596,10 +540,10 @@ void tcpconn_timeout(fd_set* set) |
596 | 540 |
|
597 | 541 |
ticks=get_ticks(); |
598 | 542 |
TCPCONN_LOCK; /* fixme: we can lock only on delete IMO */ |
599 |
- for(h=0; h<TCP_ID_HASH_SIZE; h++){ |
|
600 |
- c=tcpconn_id_hash[h]; |
|
543 |
+ for(h=0; h<TCP_ADDR_HASH_SIZE; h++){ |
|
544 |
+ c=tcpconn_addr_hash[h]; |
|
601 | 545 |
while(c){ |
602 |
- next=c->id_next; |
|
546 |
+ next=c->next; |
|
603 | 547 |
if ((c->refcnt==0) && (ticks>c->timeout)) { |
604 | 548 |
DBG("tcpconn_timeout: timeout for hash=%d - %p (%d > %d)\n", |
605 | 549 |
h, c, ticks, c->timeout); |
... | ... |
@@ -642,7 +586,7 @@ int tcp_init(struct socket_info* sock_info) |
642 | 586 |
#endif |
643 | 587 |
|
644 | 588 |
addr=&sock_info->su; |
645 |
- /* sock_info->proto=PROTO_TCP; */ |
|
589 |
+ sock_info->proto=PROTO_TCP; |
|
646 | 590 |
if (init_su(addr, &sock_info->address, sock_info->port_no)<0){ |
647 | 591 |
LOG(L_ERR, "ERROR: tcp_init: could no init sockaddr_union\n"); |
648 | 592 |
goto error; |
... | ... |
@@ -737,17 +681,19 @@ static int send2child(struct tcp_connection* tcpconn) |
737 | 681 |
|
738 | 682 |
tcp_children[idx].busy++; |
739 | 683 |
tcp_children[idx].n_reqs++; |
740 |
- tcpconn->refcnt++; |
|
741 | 684 |
if (min_busy){ |
742 |
- LOG(L_WARN, "WARNING: send2child:no free tcp receiver, " |
|
685 |
+ LOG(L_WARN, "WARNING: send2child: no free tcp receiver, " |
|
743 | 686 |
" connection passed to the least busy one (%d)\n", |
744 | 687 |
min_busy); |
745 | 688 |
} |
746 | 689 |
DBG("send2child: to tcp child %d %d(%d), %p\n", idx, |
747 | 690 |
tcp_children[idx].proc_no, |
748 | 691 |
tcp_children[idx].pid, tcpconn); |
749 |
- send_fd(tcp_children[idx].unix_sock, &tcpconn, sizeof(tcpconn), |
|
750 |
- tcpconn->s); |
|
692 |
+ if (send_fd(tcp_children[idx].unix_sock, &tcpconn, sizeof(tcpconn), |
|
693 |
+ tcpconn->s)<=0){ |
|
694 |
+ LOG(L_ERR, "ERROR: send2child: send_fd failed\n"); |
|
695 |
+ return -1; |
|
696 |
+ } |
|
751 | 697 |
|
752 | 698 |
return 0; /* just to fix a warning*/ |
753 | 699 |
} |
... | ... |
@@ -776,6 +722,8 @@ static inline void handle_new_connect(struct socket_info* si, |
776 | 722 |
/* add socket to list */ |
777 | 723 |
tcpconn=tcpconn_new(new_sock, &su, si, si->proto, S_CONN_ACCEPT); |
778 | 724 |
if (tcpconn){ |
725 |
+ tcpconn->refcnt++; /* safe, not yet available to the |
|
726 |
+ outside world */ |
|
779 | 727 |
tcpconn_add(tcpconn); |
780 | 728 |
DBG("tcp_main_loop: new connection: %p %d\n", |
781 | 729 |
tcpconn, tcpconn->s); |
... | ... |
@@ -784,6 +732,7 @@ static inline void handle_new_connect(struct socket_info* si, |
784 | 732 |
LOG(L_ERR,"ERROR: tcp_main_loop: no children " |
785 | 733 |
"available\n"); |
786 | 734 |
TCPCONN_LOCK; |
735 |
+ tcpconn->refcnt--; |
|
787 | 736 |
if (tcpconn->refcnt==0){ |
788 | 737 |
close(tcpconn->s); |
789 | 738 |
_tcpconn_rm(tcpconn); |
... | ... |
@@ -809,33 +758,24 @@ void tcp_main_loop() |
809 | 758 |
int bytes; |
810 | 759 |
struct timeval timeout; |
811 | 760 |
int fd; |
812 |
- struct socket_info* si; |
|
813 | 761 |
|
814 | 762 |
/*init */ |
815 | 763 |
maxfd=0; |
816 | 764 |
FD_ZERO(&master_set); |
817 | 765 |
/* set all the listen addresses */ |
818 |
- for (si=tcp_listen; si; si=si->next){ |
|
819 |
- if ((si->proto==PROTO_TCP) &&(si->socket!=-1)){ |
|
820 |
- FD_SET(si->socket, &master_set); |
|
821 |
- if (si->socket>maxfd) maxfd=si->socket; |
|
822 |
- }else{ |
|
823 |
- LOG(L_CRIT, "BUG: tcp_main_loop: non tcp address in tcp_listen\n"); |
|
766 |
+ for (r=0; r<sock_no; r++){ |
|
767 |
+ if ((tcp_info[r].proto==PROTO_TCP) &&(tcp_info[r].socket!=-1)){ |
|
768 |
+ FD_SET(tcp_info[r].socket, &master_set); |
|
769 |
+ if (tcp_info[r].socket>maxfd) maxfd=tcp_info[r].socket; |
|
824 | 770 |
} |
825 |
- } |
|
826 | 771 |
#ifdef USE_TLS |
827 |
- if (!tls_disable){ |
|
828 |
- for (si=tls_listen; si; si=si->next){ |
|
829 |
- if ((si->proto==PROTO_TLS) && (si->socket!=-1)){ |
|
830 |
- FD_SET(si->socket, &master_set); |
|
831 |
- if (si->socket>maxfd) maxfd=si->socket; |
|
832 |
- }else{ |
|
833 |
- LOG(L_CRIT, "BUG: tcp_main_loop: non tls address" |
|
834 |
- " in tls_listen\n"); |
|
835 |
- } |
|
772 |
+ if ((!tls_disable)&&(tls_info[r].proto==PROTO_TLS) && |
|
773 |
+ (tls_info[r].socket!=-1)){ |
|
774 |
+ FD_SET(tls_info[r].socket, &master_set); |
|
775 |
+ if (tls_info[r].socket>maxfd) maxfd=tls_info[r].socket; |
|
836 | 776 |
} |
837 |
- } |
|
838 | 777 |
#endif |
778 |
+ } |
|
839 | 779 |
/* set all the unix sockets used for child comm */ |
840 | 780 |
for (r=1; r<process_no; r++){ |
841 | 781 |
if (pt[r].unix_sock>0){ /* we can't have 0, we never close it!*/ |
... | ... |
@@ -860,18 +800,19 @@ void tcp_main_loop() |
860 | 800 |
n=0; |
861 | 801 |
} |
862 | 802 |
|
863 |
- for (si=tcp_listen; si && n; si=si->next) |
|
864 |
- handle_new_connect(si, &sel_set, &n); |
|
803 |
+ for (r=0; r<sock_no && n; r++){ |
|
804 |
+ handle_new_connect(&tcp_info[r], &sel_set, &n); |
|
865 | 805 |
#ifdef USE_TLS |
866 | 806 |
if (!tls_disable) |
867 |
- for (si=tls_listen; si && n; si=si->next) |
|
868 |
- handle_new_connect(si, &sel_set, &n); |
|
807 |
+ handle_new_connect(&tls_info[r], &sel_set, &n); |
|
869 | 808 |
#endif |
809 |
+ } |
|
870 | 810 |
|
871 | 811 |
/* check all the read fds (from the tcpconn_addr_hash ) */ |
872 |
- for (h=0; h<TCP_ID_HASH_SIZE; h++){ |
|
873 |
- for(tcpconn=tcpconn_id_hash[h]; tcpconn && n; |
|
874 |
- tcpconn=tcpconn->id_next){ |
|
812 |
+ for (h=0; h<TCP_ADDR_HASH_SIZE; h++){ |
|
813 |
+ for(tcpconn=tcpconn_addr_hash[h]; tcpconn && n; |
|
814 |
+ tcpconn=tcpconn->next){ |
|
815 |
+ /* FIXME: is refcnt==0 really necessary? */ |
|
875 | 816 |
if ((tcpconn->refcnt==0)&&(FD_ISSET(tcpconn->s, &sel_set))){ |
876 | 817 |
/* new data available */ |
877 | 818 |
n--; |
... | ... |
@@ -879,10 +820,12 @@ void tcp_main_loop() |
879 | 820 |
DBG("tcp_main_loop: data available on %p [h:%d] %d\n", |
880 | 821 |
tcpconn, h, tcpconn->s); |
881 | 822 |
FD_CLR(tcpconn->s, &master_set); |
823 |
+ tcpconn_ref(tcpconn); /* refcnt ++ */ |
|
882 | 824 |
if (send2child(tcpconn)<0){ |
883 | 825 |
LOG(L_ERR,"ERROR: tcp_main_loop: no " |
884 | 826 |
"children available\n"); |
885 | 827 |
TCPCONN_LOCK; |
828 |
+ tcpconn->refcnt--; |
|
886 | 829 |
if (tcpconn->refcnt==0){ |
887 | 830 |
fd=tcpconn->s; |
888 | 831 |
_tcpconn_rm(tcpconn); |
... | ... |
@@ -899,24 +842,21 @@ void tcp_main_loop() |
899 | 842 |
if ( (pt[r].unix_sock>0) && FD_ISSET(pt[r].unix_sock, &sel_set)){ |
900 | 843 |
/* (we can't have a fd==0, 0 is never closed )*/ |
901 | 844 |
n--; |
902 |
- /* errno==EINTR !!! TODO*/ |
|
903 |
-read_again: |
|
904 |
- bytes=read(pt[r].unix_sock, response, sizeof(response)); |
|
845 |
+ /* read until sizeof(response) |
|
846 |
+ * (this is a SOCK_STREAM so read is not atomic */ |
|
847 |
+ bytes=recv_all(pt[r].unix_sock, response, sizeof(response)); |
|
905 | 848 |
if (bytes==0){ |
906 | 849 |
/* EOF -> bad, child has died */ |
907 | 850 |
LOG(L_CRIT, "BUG: tcp_main_loop: dead child %d\n", r); |
908 | 851 |
/* don't listen on it any more */ |
909 | 852 |
FD_CLR(pt[r].unix_sock, &master_set); |
910 | 853 |
/*exit(-1);*/ |
911 |
- continue; |
|
854 |
+ continue; /* skip this and try the next one */ |
|
912 | 855 |
}else if (bytes<0){ |
913 |
- if (errno==EINTR) goto read_again; |
|
914 |
- else{ |
|
915 |
- LOG(L_CRIT, "ERROR: tcp_main_loop: read from child: " |
|
916 |
- " %s\n", strerror(errno)); |
|
917 |
- /* try to continue ? */ |
|
918 |
- continue; |
|
919 |
- } |
|
856 |
+ LOG(L_CRIT, "ERROR: tcp_main_loop: read from child: %s\n", |
|
857 |
+ strerror(errno)); |
|
858 |
+ /* try to ignore ? */ |
|
859 |
+ continue; /* skip this and try the next one */ |
|
920 | 860 |
} |
921 | 861 |
|
922 | 862 |
DBG("tcp_main_loop: read response= %lx, %ld from %d (%d)\n", |
... | ... |
@@ -949,7 +889,11 @@ read_again: |
949 | 889 |
if (pt[r].idx>=0){ |
950 | 890 |
tcp_children[pt[r].idx].busy--; |
951 | 891 |
}else{ |
952 |
- LOG(L_CRIT, "BUG: tcp_main_loop: CONN_RELEASE\n"); |
|
892 |
+ /* CON_ERROR is ok, since we can get it from |
|
893 |
+ * any process using tcp_send */ |
|
894 |
+ if (cmd!=CONN_ERROR) |
|
895 |
+ LOG(L_CRIT, "BUG: tcp_main_loop:" |
|
896 |
+ "CONN_EOF/DESTROY\n"); |
|
953 | 897 |
} |
954 | 898 |
tcpconn=(struct tcp_connection*)response[0]; |
955 | 899 |
if (tcpconn){ |
... | ... |
@@ -962,6 +906,7 @@ read_again: |
962 | 906 |
DBG("tcp_main_loop: destroying connection\n"); |
963 | 907 |
fd=tcpconn->s; |
964 | 908 |
#ifdef USE_TLS |
909 |
+ /*FIXME: lock ->writelock ? */ |
|
965 | 910 |
if (tcpconn->type==PROTO_TLS) |
966 | 911 |
tls_close(tcpconn, fd); |
967 | 912 |
#endif |
... | ... |
@@ -983,8 +928,11 @@ read_again: |
983 | 928 |
/* WARNING: take care of setting refcnt properly to |
984 | 929 |
* avoid race condition */ |
985 | 930 |
if (tcpconn){ |
986 |
- send_fd(pt[r].unix_sock, &tcpconn, |
|
987 |
- sizeof(tcpconn), tcpconn->s); |
|
931 |
+ if (send_fd(pt[r].unix_sock, &tcpconn, |
|
932 |
+ sizeof(tcpconn), tcpconn->s)<=0){ |
|
933 |
+ LOG(L_ERR, "ERROR: tcp_main_loop:" |
|
934 |
+ "send_fd failed\n"); |
|
935 |
+ } |
|
988 | 936 |
}else{ |
989 | 937 |
LOG(L_CRIT, "BUG: tcp_main_loop: null pointer\n"); |
990 | 938 |
} |
... | ... |
@@ -995,8 +943,20 @@ read_again: |
995 | 943 |
/* WARNING: take care of setting refcnt properly to |
996 | 944 |
* avoid race condition */ |
997 | 945 |
if (tcpconn){ |
998 |
- receive_fd(pt[r].unix_sock, &tcpconn, |
|
999 |
- sizeof(tcpconn), &tcpconn->s); |
|
946 |
+ bytes=receive_fd(pt[r].unix_sock, &tcpconn, |
|
947 |
+ sizeof(tcpconn), &tcpconn->s); |
|
948 |
+ if (bytes<sizeof(tcpconn)){ |
|
949 |
+ if (bytes<0){ |
|
950 |
+ LOG(L_CRIT, "BUG: tcp_main_loop:" |
|
951 |
+ " CONN_NEW: receive_fd " |
|
952 |
+ "failed\n"); |
|
953 |
+ }else{ |
|
954 |
+ LOG(L_CRIT, "BUG: tcp_main_loop:" |
|
955 |
+ " CONN_NEW: to few bytes " |
|
956 |
+ "received (%d)\n", bytes ); |
|
957 |
+ } |
|
958 |
+ break; /* try to ignore */ |
|
959 |
+ } |
|
1000 | 960 |
/* add tcpconn to the list*/ |
1001 | 961 |
tcpconn_add(tcpconn); |
1002 | 962 |
FD_SET(tcpconn->s, &master_set); |
... | ... |
@@ -1012,7 +972,7 @@ read_again: |
1012 | 972 |
cmd); |
1013 | 973 |
} |
1014 | 974 |
} |
1015 |
- } |
|
975 |
+ } /* for */ |
|
1016 | 976 |
|
1017 | 977 |
/* remove old connections */ |
1018 | 978 |
tcpconn_timeout(&master_set); |
... | ... |
@@ -1047,9 +1007,10 @@ int init_tcp() |
1047 | 1007 |
} |
1048 | 1008 |
*connection_id=1; |
1049 | 1009 |
/* alloc hashtables*/ |
1050 |
- tcpconn_aliases_hash=(struct tcp_conn_alias**) |
|
1051 |
- shm_malloc(TCP_ALIAS_HASH_SIZE* sizeof(struct tcp_conn_alias*)); |
|
1052 |
- if (tcpconn_aliases_hash==0){ |
|
1010 |
+ tcpconn_addr_hash=(struct tcp_connection**)shm_malloc(TCP_ADDR_HASH_SIZE* |
|
1011 |
+ sizeof(struct tcp_connection*)); |
|
1012 |
+ |
|
1013 |
+ if (tcpconn_addr_hash==0){ |
|
1053 | 1014 |
LOG(L_CRIT, "ERROR: init_tcp: could not alloc address hashtable\n"); |
1054 | 1015 |
shm_free(connection_id); |
1055 | 1016 |
connection_id=0; |
... | ... |
@@ -1065,16 +1026,16 @@ int init_tcp() |
1065 | 1026 |
LOG(L_CRIT, "ERROR: init_tcp: could not alloc id hashtable\n"); |
1066 | 1027 |
shm_free(connection_id); |
1067 | 1028 |
connection_id=0; |
1068 |
- shm_free(tcpconn_aliases_hash); |
|
1069 |
- tcpconn_aliases_hash=0; |
|
1029 |
+ shm_free(tcpconn_addr_hash); |
|
1030 |
+ tcpconn_addr_hash=0; |
|
1070 | 1031 |
lock_destroy(tcpconn_lock); |
1071 | 1032 |
lock_dealloc((void*)tcpconn_lock); |
1072 | 1033 |
tcpconn_lock=0; |
1073 | 1034 |
goto error; |
1074 | 1035 |
} |
1075 | 1036 |
/* init hashtables*/ |
1076 |
- memset((void*)tcpconn_aliases_hash, 0, |
|
1077 |
- TCP_ALIAS_HASH_SIZE * sizeof(struct tcp_conn_alias*)); |
|
1037 |
+ memset((void*)tcpconn_addr_hash, 0, |
|
1038 |
+ TCP_ADDR_HASH_SIZE * sizeof(struct tcp_connection*)); |
|
1078 | 1039 |
memset((void*)tcpconn_id_hash, 0, |
1079 | 1040 |
TCP_ID_HASH_SIZE * sizeof(struct tcp_connection*)); |
1080 | 1041 |
return 0; |
... | ... |
@@ -1092,9 +1053,9 @@ void destroy_tcp() |
1092 | 1053 |
lock_dealloc((void*)tcpconn_lock); |
1093 | 1054 |
tcpconn_lock=0; |
1094 | 1055 |
} |
1095 |
- if(tcpconn_aliases_hash){ |
|
1096 |
- shm_free(tcpconn_aliases_hash); |
|
1097 |
- tcpconn_aliases_hash=0; |
|
1056 |
+ if(tcpconn_addr_hash){ |
|
1057 |
+ shm_free(tcpconn_addr_hash); |
|
1058 |
+ tcpconn_addr_hash=0; |
|
1098 | 1059 |
} |
1099 | 1060 |
if(tcpconn_id_hash){ |
1100 | 1061 |
shm_free(tcpconn_id_hash); |
... | ... |
@@ -1152,6 +1113,7 @@ int tcp_init_children() |
1152 | 1113 |
unix_tcp_sock=sockfd[1]; |
1153 | 1114 |
bind_address=0; /* force a SEGFAULT if someone uses a non-init. |
1154 | 1115 |
bind address on tcp */ |
1116 |
+ bind_idx=0; |
|
1155 | 1117 |
if (init_child(r+children_no+1) < 0) { |
1156 | 1118 |
LOG(L_ERR, "init_children failed\n"); |
1157 | 1119 |
goto error; |
... | ... |
@@ -547,7 +547,8 @@ void release_tcpconn(struct tcp_connection* c, long state, int unix_sock) |
547 | 547 |
/* errno==EINTR, EWOULDBLOCK a.s.o todo */ |
548 | 548 |
response[0]=(long)c; |
549 | 549 |
response[1]=state; |
550 |
- write(unix_sock, response, sizeof(response)); |
|
550 |
+ if (send_all(unix_sock, response, sizeof(response))<=0) |
|
551 |
+ LOG(L_ERR, "ERROR: release_tcpconn: send_all failed\n"); |
|
551 | 552 |
} |
552 | 553 |
|
553 | 554 |
|
... | ... |
@@ -625,9 +626,6 @@ void tcp_receive_loop(int unix_sock) |
625 | 626 |
release_tcpconn(con, resp, unix_sock); |
626 | 627 |
goto skip; |
627 | 628 |
} |
628 |
-#ifdef USE_TLS |
|
629 |
- if (con->type==PROTO_TLS) tls_tcpconn_update_fd(con, s); |
|
630 |
-#endif |
|
631 | 629 |
con->timeout=get_ticks()+TCP_CHILD_TIMEOUT; |
632 | 630 |
FD_SET(s, &master_set); |
633 | 631 |
if (maxfd<s) maxfd=s; |
... | ... |
@@ -646,7 +644,21 @@ skip: |
646 | 644 |
DBG("tcp receive: match, fd:isset\n"); |
647 | 645 |
#endif |
648 | 646 |
nfds--; |
649 |
- resp=tcp_read_req(con); |
|
647 |
+#ifdef USE_TLS |
|
648 |
+ if (con->type==PROTO_TLS){ |
|
649 |
+ /* we have to avoid to run in the same time |
|
650 |
+ * with a tls_write becasue of the |
|
651 |
+ * update_fd stuff (we don't want a write |
|
652 |
+ * stealing the fd under us or vice versa) |
|
653 |
+ * => lock on con->write_lock (ugly hack) */ |
|
654 |
+ lock_get(&con->write_lock); |
|
655 |
+ tls_tcpconn_update_fd(con, s); |
|
656 |
+ resp=tcp_read_req(con); |
|
657 |
+ lock_release(&con->write_lock); |
|
658 |
+ }else |
|
659 |
+#else |
|
660 |
+ resp=tcp_read_req(con); |
|
661 |
+#endif |
|
650 | 662 |
if (resp<0){ |
651 | 663 |
FD_CLR(con->fd, &master_set); |
652 | 664 |
tcpconn_listrm(list, con, c_next, c_prev); |