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