Browse code

- replaced tcp_blocking_write with more generic tsend_stream(fd, buf, len, timeout) & tsend_dgram(fd, buf, len, timeout, to, tolen) so that they can be used from ser modules a.s.o.

Andrei Pelinescu-Onciul authored on 26/02/2004 18:00:49
Showing 4 changed files
... ...
@@ -2,6 +2,7 @@ $Id$
2 2
 
3 3
 ( - todo, x - done)
4 4
 
5
+- [doc] document force_rport()
5 6
 - [fifo] fix fgets error handling (it does not set errno always,
6 7
    , right now kills all ser if interrupted by a signal on ?solaris?)
7 8
 - [mem] make shm_realloc be fragmentation friendly: call shm_compact_frags
... ...
@@ -93,6 +93,7 @@
93 93
 #include "sr_module.h"
94 94
 #include "tcp_server.h"
95 95
 #include "tcp_init.h"
96
+#include "tsend.h"
96 97
 #ifdef USE_TLS
97 98
 #include "tls/tls_server.h"
98 99
 #endif
... ...
@@ -236,6 +237,7 @@ end:
236 237
 
237 238
 
238 239
 
240
+#if 0
239 241
 /* blocking write even on non-blocking sockets 
240 242
  * if TCP_TIMEOUT will return with error */
241 243
 static int tcp_blocking_write(struct tcp_connection* c, int fd, char* buf,
... ...
@@ -303,6 +305,7 @@ error:
303 305
 end:
304 306
 		return initial_len;
305 307
 }
308
+#endif
306 309
 
307 310
 
308 311
 
... ...
@@ -754,7 +757,8 @@ send_it:
754 757
 		n=tls_blocking_write(c, fd, buf, len);
755 758
 	else
756 759
 #endif
757
-		n=tcp_blocking_write(c, fd, buf, len);
760
+		/* n=tcp_blocking_write(c, fd, buf, len); */
761
+		n=tsend_stream(fd, buf, len, tcp_send_timeout*1000); 
758 762
 	lock_release(&c->write_lock);
759 763
 	DBG("tcp_send: after write: c= %p n=%d fd=%d\n",c, n, fd);
760 764
 	DBG("tcp_send: buf=\n%.*s\n", (int)len, buf);
761 765
new file mode 100644
... ...
@@ -0,0 +1,176 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2001-2003 Fhg Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
8
+ * ser is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * For a license to use the ser software under conditions
14
+ * other than those described here, or to purchase support for this
15
+ * software, please contact iptel.org by e-mail at the following addresses:
16
+ *    info@iptel.org
17
+ *
18
+ * ser is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License
24
+ * along with this program; if not, write to the Free Software
25
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
+ */
27
+/*
28
+ * send with timeout for stream and datagram sockets
29
+ * 
30
+ * History:
31
+ * --------
32
+ *  2004-02-26  created by andrei
33
+ */
34
+
35
+#include <string.h>
36
+#include <errno.h>
37
+#include <sys/poll.h>
38
+
39
+#include <sys/types.h>
40
+#include <sys/socket.h>
41
+
42
+#include "dprint.h"
43
+
44
+
45
+/* sends on fd (which must be O_NONBLOCK); if it cannot send any data
46
+ * in timeout miliseconds it will return ERROR
47
+ * returns: -1 on error, or number of bytes written
48
+ *  (if less than len => couldn't send all)
49
+ *  bugs: signals will reset the timer
50
+ */
51
+int tsend_stream(int fd, char* buf, unsigned int len, int timeout)
52
+{
53
+	int n;
54
+	int written;
55
+	int initial_len;
56
+	struct pollfd pf;
57
+	
58
+	written=0;
59
+	initial_len=len;
60
+	pf.fd=fd;
61
+	pf.events=POLLIN;
62
+	
63
+again:
64
+	n=send(fd, buf, len,
65
+#ifdef HAVE_MSG_NOSIGNAL
66
+			MSG_NOSIGNAL
67
+#else
68
+			0
69
+#endif
70
+		);
71
+	if (n<0){
72
+		if (errno==EINTR) goto again;
73
+		else if (errno!=EAGAIN && errno!=EWOULDBLOCK){
74
+			LOG(L_ERR, "ERROR: tsend_stream: failed to send: (%d) %s\n",
75
+						errno, strerror(errno));
76
+			goto error;
77
+		}
78
+	}
79
+	written+=n;
80
+	if (n<len){
81
+		/* partial write */
82
+		buf+=n;
83
+		len-=n;
84
+	}else{
85
+		/* succesfull full write */
86
+		goto end;
87
+	}
88
+	while(1){
89
+		pf.revents=0;
90
+		n=poll(&pf, 1, timeout);
91
+		if (n<0){
92
+			if (errno==EINTR) continue; /* signal, ignore */
93
+			LOG(L_ERR, "ERROR: tsend_stream: poll failed: %s [%d]\n",
94
+					strerror(errno), errno);
95
+			goto error;
96
+		}else if (n==0){
97
+			/* timeout */
98
+			LOG(L_ERR, "ERROR: tsend_stream: send timeout (%d)\n", timeout);
99
+			goto error;
100
+		}
101
+		if (pf.revents&POLLIN){
102
+			/* we can write again */
103
+			goto again;
104
+		}
105
+	}
106
+error:
107
+	return -1;
108
+end:
109
+	return written;
110
+}
111
+
112
+
113
+
114
+/* sends on dram fd (which must be O_NONBLOCK); if it cannot send any data
115
+ * in timeout miliseconds it will return ERROR
116
+ * returns: -1 on error, or number of bytes written
117
+ *  (if less than len => couldn't send all)
118
+ *  bugs: signals will reset the timer
119
+ */
120
+int tsend_dgram(int fd, char* buf, unsigned int len, int timeout,
121
+				const struct sockaddr* to, socklen_t tolen)
122
+{
123
+	int n;
124
+	int written;
125
+	int initial_len;
126
+	struct pollfd pf;
127
+	
128
+	written=0;
129
+	initial_len=len;
130
+	pf.fd=fd;
131
+	pf.events=POLLIN;
132
+	
133
+again:
134
+	n=sendto(fd, buf, len, 0, to, tolen);
135
+	if (n<0){
136
+		if (errno==EINTR) goto again;
137
+		else if (errno!=EAGAIN && errno!=EWOULDBLOCK){
138
+			LOG(L_ERR, "ERROR: tsend_dgram: failed to send: (%d) %s\n",
139
+						errno, strerror(errno));
140
+			goto error;
141
+		}
142
+	}
143
+	written+=n;
144
+	if (n<len){
145
+		/* partial write */
146
+		LOG(L_CRIT, "BUG: tsend_dgram: partial write on datagram socket\n");
147
+		goto error;
148
+	}else{
149
+		/* succesfull full write */
150
+		goto end;
151
+	}
152
+	while(1){
153
+		pf.revents=0;
154
+		n=poll(&pf, 1, timeout);
155
+		if (n<0){
156
+			if (errno==EINTR) continue; /* signal, ignore */
157
+			LOG(L_ERR, "ERROR: tsend_dgram: poll failed: %s [%d]\n",
158
+					strerror(errno), errno);
159
+			goto error;
160
+		}else if (n==0){
161
+			/* timeout */
162
+			LOG(L_ERR, "ERROR: tsend_dgram: send timeout (%d)\n", timeout);
163
+			goto error;
164
+		}
165
+		if (pf.revents&POLLIN){
166
+			/* we can write again */
167
+			goto again;
168
+		}
169
+	}
170
+error:
171
+	return -1;
172
+end:
173
+	return written;
174
+}
175
+
176
+	
0 177
new file mode 100644
... ...
@@ -0,0 +1,45 @@
1
+/*
2
+ * $Id$
3
+ *
4
+ * Copyright (C) 2001-2003 Fhg Fokus
5
+ *
6
+ * This file is part of ser, a free SIP server.
7
+ *
8
+ * ser is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version
12
+ *
13
+ * For a license to use the ser software under conditions
14
+ * other than those described here, or to purchase support for this
15
+ * software, please contact iptel.org by e-mail at the following addresses:
16
+ *    info@iptel.org
17
+ *
18
+ * ser is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License
24
+ * along with this program; if not, write to the Free Software
25
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
+ */
27
+/*
28
+ *  History:
29
+ * --------
30
+ *  2004-02-26  created by andrei
31
+ */
32
+
33
+#ifndef __tsend_h
34
+#define __tsend_h
35
+
36
+
37
+int tsend_stream(int fd, char* buf, unsigned int len, int timeout);
38
+int tsend_dgram(int fd, char* buf, unsigned int len, int timeout,
39
+				const struct sockaddr* to, socklen_t tolen);
40
+
41
+
42
+
43
+#endif
44
+
45
+