Browse code

- added tsend_dgram_ev (== writev+timeout) - changed parameter order for tsend_dgram

Andrei Pelinescu-Onciul authored on 03/03/2004 11:13:25
Showing 2 changed files
... ...
@@ -30,6 +30,7 @@
30 30
  * History:
31 31
  * --------
32 32
  *  2004-02-26  created by andrei
33
+ *  2003-03-03  switched to heavy macro use, added tsend_dgram_ev (andrei) 
33 34
  */
34 35
 
35 36
 #include <string.h>
... ...
@@ -38,9 +39,56 @@
38 39
 
39 40
 #include <sys/types.h>
40 41
 #include <sys/socket.h>
42
+#include <sys/uio.h>
41 43
 
42 44
 #include "dprint.h"
43 45
 
46
+/* the functions below are very similar => some generic macros */
47
+#define TSEND_INIT \
48
+	int n; \
49
+	struct pollfd pf; \
50
+	pf.fd=fd; \
51
+	pf.events=POLLOUT
52
+
53
+#define TSEND_POLL(f_name) \
54
+poll_loop: \
55
+	while(1){ \
56
+		n=poll(&pf, 1, timeout); \
57
+		if (n<0){ \
58
+			if (errno==EINTR) continue; /* signal, ignore */ \
59
+			LOG(L_ERR, "ERROR: " f_name ": poll failed: %s [%d]\n", \
60
+					strerror(errno), errno); \
61
+			goto error; \
62
+		}else if (n==0){ \
63
+			/* timeout */ \
64
+			LOG(L_ERR, "ERROR: " f_name ": send timeout (%d)\n", timeout); \
65
+			goto error; \
66
+		} \
67
+		if (pf.revents&POLLOUT){ \
68
+			/* we can write again */ \
69
+			goto again; \
70
+		}else if (pf.revents&(POLLERR|POLLHUP|POLLNVAL)){ \
71
+			LOG(L_ERR, "ERROR: " f_name ": bad poll flags %x\n", \
72
+					pf.revents); \
73
+			goto error; \
74
+		} \
75
+		/* if POLLIN or POLLPRI or other non-harmfull events happened,    \
76
+		 * continue ( although poll should never signal them since we're  \
77
+		 * not interested in them => we should never reach this point) */ \
78
+	} 
79
+
80
+
81
+#define TSEND_ERR_CHECK(f_name)\
82
+	if (n<0){ \
83
+		if (errno==EINTR) goto again; \
84
+		else if (errno!=EAGAIN && errno!=EWOULDBLOCK){ \
85
+			LOG(L_ERR, "ERROR: " f_name ": failed to send: (%d) %s\n", \
86
+					errno, strerror(errno)); \
87
+			goto error; \
88
+		}else goto poll_loop; \
89
+	}
90
+	
91
+
44 92
 
45 93
 /* sends on fd (which must be O_NONBLOCK); if it cannot send any data
46 94
  * in timeout miliseconds it will return ERROR
... ...
@@ -50,17 +98,10 @@
50 98
  */
51 99
 int tsend_stream(int fd, char* buf, unsigned int len, int timeout)
52 100
 {
53
-	int n;
54 101
 	int written;
55
-	int initial_len;
56
-	struct pollfd pf;
102
+	TSEND_INIT;
57 103
 	
58 104
 	written=0;
59
-	initial_len=len;
60
-	pf.fd=fd;
61
-	pf.events=POLLOUT;
62
-	
63
-	
64 105
 again:
65 106
 	n=send(fd, buf, len,
66 107
 #ifdef HAVE_MSG_NOSIGNAL
... ...
@@ -69,121 +110,61 @@ again:
69 110
 			0
70 111
 #endif
71 112
 		);
72
-	if (n<0){
73
-		if (errno==EINTR) goto again;
74
-		else if (errno!=EAGAIN && errno!=EWOULDBLOCK){
75
-			LOG(L_ERR, "ERROR: tsend_stream: failed to send: (%d) %s\n",
76
-						errno, strerror(errno));
77
-			goto error;
78
-		}
79
-	}
80
-	written+=n;
81
-	if (n<len){
82
-		/* partial write */
83
-		buf+=n;
84
-		len-=n;
85
-	}else{
86
-		/* succesfull full write */
87
-		goto end;
88
-	}
89
-	while(1){
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&POLLOUT){
102
-			/* we can write again */
103
-			goto again;
104
-		}else if (pf.revents&(POLLERR|POLLHUP|POLLNVAL)){
105
-			LOG(L_ERR, "ERROR: tsend_stream: bad poll flags %x\n", 
106
-					pf.revents);
107
-			goto error;
108
-		}
109
-		/* if POLLIN or POLLPRI or other non-harmfull events happened,
110
-		 * continue ( although poll should never signal them since we're
111
-		 * not interested in them => we should never reach this point) */
113
+	TSEND_ERR_CHECK("tsend_stream");
114
+	written+=n; 
115
+	if (n<len){ 
116
+		/* partial write */ 
117
+		buf+=n; 
118
+		len-=n; 
119
+	}else{ 
120
+		/* succesfull full write */ 
121
+		return written;
112 122
 	}
123
+	TSEND_POLL("tsend_stream");
113 124
 error:
114 125
 	return -1;
115
-end:
116
-	return written;
117 126
 }
118 127
 
119 128
 
120 129
 
121
-/* sends on dram fd (which must be O_NONBLOCK); if it cannot send any data
130
+/* sends on dgram fd (which must be O_NONBLOCK); if it cannot send any data
122 131
  * in timeout miliseconds it will return ERROR
123 132
  * returns: -1 on error, or number of bytes written
124 133
  *  (if less than len => couldn't send all)
125 134
  *  bugs: signals will reset the timer
126 135
  */
127
-int tsend_dgram(int fd, char* buf, unsigned int len, int timeout,
128
-				const struct sockaddr* to, socklen_t tolen)
136
+int tsend_dgram(int fd, char* buf, unsigned int len, 
137
+				const struct sockaddr* to, socklen_t tolen, int timeout)
129 138
 {
130
-	int n;
131
-	int written;
132
-	int initial_len;
133
-	struct pollfd pf;
134
-	
135
-	written=0;
136
-	initial_len=len;
137
-	pf.fd=fd;
138
-	pf.events=POLLOUT;
139
-	
139
+	TSEND_INIT;
140 140
 again:
141 141
 	n=sendto(fd, buf, len, 0, to, tolen);
142
-	if (n<0){
143
-		if (errno==EINTR) goto again;
144
-		else if (errno!=EAGAIN && errno!=EWOULDBLOCK){
145
-			LOG(L_ERR, "ERROR: tsend_dgram: failed to send: (%d) %s\n",
146
-						errno, strerror(errno));
147
-			goto error;
148
-		}
149
-	}
150
-	written+=n;
151
-	if (n<len){
152
-		/* partial write */
153
-		LOG(L_CRIT, "BUG: tsend_dgram: partial write on datagram socket\n");
154
-		goto error;
155
-	}else{
156
-		/* succesfull full write */
157
-		goto end;
158
-	}
159
-	while(1){
160
-		n=poll(&pf, 1, timeout);
161
-		if (n<0){
162
-			if (errno==EINTR) continue; /* signal, ignore */
163
-			LOG(L_ERR, "ERROR: tsend_dgram: poll failed: %s [%d]\n",
164
-					strerror(errno), errno);
165
-			goto error;
166
-		}else if (n==0){
167
-			/* timeout */
168
-			LOG(L_ERR, "ERROR: tsend_dgram: send timeout (%d)\n", timeout);
169
-			goto error;
170
-		}
171
-		if (pf.revents&POLLOUT){
172
-			/* we can write again */
173
-			goto again;
174
-		}else if (pf.revents&(POLLERR|POLLHUP|POLLNVAL)){
175
-			LOG(L_ERR, "ERROR: tsend_dgram: bad poll flags %x\n", 
176
-					pf.revents);
177
-			goto error;
178
-		}
179
-		/* if POLLIN or POLLPRI or other non-harmfull events happened,
180
-		 * continue ( although poll should never signal them since we're
181
-		 * not interested in them => we should never reach this point) */
182
-	}
142
+	TSEND_ERR_CHECK("tsend_dgram");
143
+	/* we don't care about partial writes: they shouln't happen on 
144
+	 * a datagram socket */
145
+	return n;
146
+	TSEND_POLL("tsend_datagram");
183 147
 error:
184 148
 	return -1;
185
-end:
186
-	return written;
187 149
 }
188 150
 
189 151
 	
152
+/* sends on connected datagram fd (which must be O_NONBLOCK); 
153
+ * if it cannot send any data in timeout miliseconds it will return ERROR
154
+ * returns: -1 on error, or number of bytes written
155
+ *  (if less than len => couldn't send all)
156
+ *  bugs: signals will reset the timer
157
+ */
158
+
159
+int tsend_dgram_ev(int fd, const struct iovec* v, int count, int timeout)
160
+{
161
+	TSEND_INIT;
162
+again:
163
+	n=writev(fd, v, count);
164
+	TSEND_ERR_CHECK("tsend_datagram_ev");
165
+	return n;
166
+	TSEND_POLL("tsend_datagram_ev");
167
+error:
168
+	return -1;
169
+}
170
+
... ...
@@ -35,8 +35,9 @@
35 35
 
36 36
 
37 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);
38
+int tsend_dgram(int fd, char* buf, unsigned int len, 
39
+				const struct sockaddr* to, socklen_t tolen, int timeout);
40
+int tsend_dgram_ev(int fd, const struct iovec* v, int count, int timeout);
40 41
 
41 42
 
42 43