... | ... |
@@ -46,6 +46,9 @@ |
46 | 46 |
#define TCP_BUF_SIZE 65535 |
47 | 47 |
#define TCP_CON_TIMEOUT 120 /* in seconds */ |
48 | 48 |
#define TCP_CON_SEND_TIMEOUT 120 /* timeout after a send */ |
49 |
+#define TCP_SEND_TIMEOUT 10 /* if a send doesn't complete in 10s, timeout */ |
|
50 |
+#define TCP_CONNECT_TIMEOUT 10 /* if a connect doesn't complete in this time, |
|
51 |
+ timeout */ |
|
49 | 52 |
#define TCP_CHILD_TIMEOUT 5 /* after 5 seconds, the child "returns" |
50 | 53 |
the connection to the tcp master process */ |
51 | 54 |
#define TCP_MAIN_SELECT_TIMEOUT 5 /* how often "tcp main" checks for timeout*/ |
... | ... |
@@ -50,6 +50,9 @@ |
50 | 50 |
* to/from readers/writers (andrei) |
51 | 51 |
* 2003-11-17 handle_new_connect & tcp_connect will close the |
52 | 52 |
* new socket if tcpconn_new return 0 (e.g. out of mem) (andrei) |
53 |
+ * 2003-11-28 tcp_blocking_write & tcp_blocking_connect added (andrei) |
|
54 |
+ * TODO: switch to non-blocking tcp sockets, replace send & connect |
|
55 |
+ * with tcp_blocking_* |
|
53 | 56 |
*/ |
54 | 57 |
|
55 | 58 |
|
... | ... |
@@ -480,6 +483,139 @@ void tcpconn_put(struct tcp_connection* c) |
480 | 483 |
} |
481 | 484 |
|
482 | 485 |
|
486 |
+static int tcp_blocking_connect(int fd, const struct sockaddr *servaddr, |
|
487 |
+ socklen_t addrlen) |
|
488 |
+{ |
|
489 |
+ int n; |
|
490 |
+ fd_set sel_set; |
|
491 |
+ struct timeval timeout; |
|
492 |
+ int ticks; |
|
493 |
+ int err; |
|
494 |
+ int err_len; |
|
495 |
+ |
|
496 |
+again: |
|
497 |
+ n=connect(fd, servaddr, addrlen); |
|
498 |
+ if (n==-1){ |
|
499 |
+ if (errno==EINTR) goto again; |
|
500 |
+ if (errno!=EINPROGRESS && errno!=EALREADY){ |
|
501 |
+ LOG(L_ERR, "ERROR: tcp_blocking_connect: (%d) %s\n", |
|
502 |
+ errno, strerror(errno)); |
|
503 |
+ goto error; |
|
504 |
+ } |
|
505 |
+ }else goto end; |
|
506 |
+ |
|
507 |
+ while(1){ |
|
508 |
+ FD_ZERO(&sel_set); |
|
509 |
+ FD_SET(fd, &sel_set); |
|
510 |
+ timeout.tv_sec=TCP_CONNECT_TIMEOUT; |
|
511 |
+ timeout.tv_usec=0; |
|
512 |
+ ticks=get_ticks(); |
|
513 |
+ n=select(fd+1, 0, &sel_set, 0, &timeout); |
|
514 |
+ if (n<0){ |
|
515 |
+ if (errno==EINTR) continue; |
|
516 |
+ LOG(L_ERR, "ERROR: tcp_blocking_connect: select failed: (%d) %s\n", |
|
517 |
+ errno, strerror(errno)); |
|
518 |
+ goto error; |
|
519 |
+ }else if (n==0){ |
|
520 |
+ /* timeout */ |
|
521 |
+ if (get_ticks()-ticks>=TCP_CONNECT_TIMEOUT){ |
|
522 |
+ LOG(L_ERR, "ERROR: tcp_blocking_connect: send timeout\n"); |
|
523 |
+ goto error; |
|
524 |
+ } |
|
525 |
+ continue; |
|
526 |
+ } |
|
527 |
+ if (FD_ISSET(fd, &sel_set)){ |
|
528 |
+ err_len=sizeof(err); |
|
529 |
+ getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &err_len); |
|
530 |
+ if (err==0) goto end; |
|
531 |
+ if (err!=EINPROGRESS && err!=EALREADY){ |
|
532 |
+ LOG(L_ERR, "ERROR: tcp_blocking_connect: SO_ERROR (%d) %s\n", |
|
533 |
+ err, strerror(err)); |
|
534 |
+ goto error; |
|
535 |
+ } |
|
536 |
+ } |
|
537 |
+ } |
|
538 |
+error: |
|
539 |
+ return -1; |
|
540 |
+end: |
|
541 |
+ return 0; |
|
542 |
+} |
|
543 |
+ |
|
544 |
+ |
|
545 |
+ |
|
546 |
+/* blocking write even on non-blocking sockets |
|
547 |
+ * if TCP_TIMEOUT will return with error */ |
|
548 |
+static int tcp_blocking_write(struct tcp_connection* c, int fd, char* buf, |
|
549 |
+ unsigned int len) |
|
550 |
+{ |
|
551 |
+ int n; |
|
552 |
+ fd_set sel_set; |
|
553 |
+ struct timeval timeout; |
|
554 |
+ int ticks; |
|
555 |
+ int initial_len; |
|
556 |
+ |
|
557 |
+ initial_len=len; |
|
558 |
+again: |
|
559 |
+ /* try first without select */ |
|
560 |
+ if (c->state==S_CONN_CONNECT){ |
|
561 |
+ /* connect not finished, try again ? */ |
|
562 |
+ LOG(L_CRIT, "BUG: tcp_blocking_write: connect not implemented yet\n"); |
|
563 |
+ goto error; |
|
564 |
+ } |
|
565 |
+ n=send(fd, buf, len, |
|
566 |
+#ifdef HAVE_MSG_NOSIGNAL |
|
567 |
+ MSG_NOSIGNAL |
|
568 |
+#else |
|
569 |
+ 0 |
|
570 |
+#endif |
|
571 |
+ ); |
|
572 |
+ if (n<0){ |
|
573 |
+ if (errno==EINTR) goto again; |
|
574 |
+ else if (errno!=EAGAIN && errno!=EWOULDBLOCK){ |
|
575 |
+ LOG(L_ERR, "tcp_blocking_write: failed to send: (%d) %s\n", |
|
576 |
+ errno, strerror(errno)); |
|
577 |
+ goto error; |
|
578 |
+ } |
|
579 |
+ }else if (n<len){ |
|
580 |
+ /* partial write */ |
|
581 |
+ buf+=n; |
|
582 |
+ len-=n; |
|
583 |
+ }else{ |
|
584 |
+ /* success: full write */ |
|
585 |
+ goto end; |
|
586 |
+ } |
|
587 |
+ while(1){ |
|
588 |
+ FD_ZERO(&sel_set); |
|
589 |
+ FD_SET(fd, &sel_set); |
|
590 |
+ timeout.tv_sec=TCP_SEND_TIMEOUT; |
|
591 |
+ timeout.tv_usec=0; |
|
592 |
+ ticks=get_ticks(); |
|
593 |
+ n=select(fd+1, 0, &sel_set, 0, &timeout); |
|
594 |
+ if (n<0){ |
|
595 |
+ if (errno==EINTR) continue; /* signal, ignore */ |
|
596 |
+ LOG(L_ERR, "ERROR: tcp_blocking_write: select failed: " |
|
597 |
+ " (%d) %s\n", errno, strerror(errno)); |
|
598 |
+ goto error; |
|
599 |
+ }else if (n==0){ |
|
600 |
+ /* timeout */ |
|
601 |
+ if (get_ticks()-ticks>=TCP_SEND_TIMEOUT){ |
|
602 |
+ LOG(L_ERR, "ERROR: tcp_blocking_write: send timeout\n"); |
|
603 |
+ goto error; |
|
604 |
+ } |
|
605 |
+ continue; |
|
606 |
+ } |
|
607 |
+ if (FD_ISSET(fd, &sel_set)){ |
|
608 |
+ /* we can write again */ |
|
609 |
+ goto again; |
|
610 |
+ } |
|
611 |
+ } |
|
612 |
+error: |
|
613 |
+ return -1; |
|
614 |
+end: |
|
615 |
+ return initial_len; |
|
616 |
+} |
|
617 |
+ |
|
618 |
+ |
|
483 | 619 |
|
484 | 620 |
/* finds a tcpconn & sends on it */ |
485 | 621 |
int tcp_send(int type, char* buf, unsigned len, union sockaddr_union* to, |