ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/vpn_tcp.C
(Generate patch)

Comparing gvpe/src/vpn_tcp.C (file contents):
Revision 1.2 by pcg, Sun Apr 6 18:12:18 2003 UTC vs.
Revision 1.3 by pcg, Sun Apr 6 20:01:53 2003 UTC

73 enum { ERROR, IDLE, CONNECTING, ESTABLISHED } state; 73 enum { ERROR, IDLE, CONNECTING, ESTABLISHED } state;
74 74
75 vpn_packet *r_pkt; 75 vpn_packet *r_pkt;
76 u32 r_len, r_ofs; 76 u32 r_len, r_ofs;
77 77
78 vpn_packet *w_pkt;
79 u32 w_len, w_ofs;
80
78 void tcpv4_ev (io_watcher &w, short revents); 81 void tcpv4_ev (io_watcher &w, short revents);
79 82
80 bool send_packet (vpn_packet *pkt, int tos); 83 bool send_packet (vpn_packet *pkt, int tos);
84 bool write_packet ();
81 85
82 void error (); // abort conenction && cleanup 86 void error (); // abort conenction && cleanup
83 87
84 operator tcp_si_map::value_type() 88 operator tcp_si_map::value_type()
85 { 89 {
154 { 158 {
155 close (fd); 159 close (fd);
156 fd = -1; 160 fd = -1;
157 } 161 }
158 162
159 delete r_pkt; 163 delete r_pkt; r_pkt = 0;
160 r_pkt = 0; 164 delete w_pkt; w_pkt = 0;
161 165
162 stop (); 166 stop ();
163 state = active ? IDLE : ERROR; 167 state = active ? IDLE : ERROR;
164} 168}
165 169
170bool
171tcp_connection::write_packet ()
172{
173 ssize_t len;
174
175 if (w_ofs < 2)
176 {
177 u16 plen = htons (w_pkt->len);
178
179 iovec vec[2];
180 vec[0].iov_base = ((u8 *)&plen) + w_ofs;
181 vec[0].iov_len = 2 - w_ofs;
182 vec[1].iov_base = &((*w_pkt)[0]);
183 vec[1].iov_len = w_len - 2;
184
185 len = writev (fd, vec, 2);
186 }
187 else
188 len = write (fd, &((*w_pkt)[w_ofs - 2]), w_len);
189
190 if (len > 0)
191 {
192 w_ofs += len;
193 w_len -= len;
194
195 return w_len == 0;
196 }
197 else if (len < 0 && (errno == EAGAIN || errno == EINTR))
198 return false;
199 else
200 {
201 error ();
202 return false;
203 }
204}
205
166void 206void
167tcp_connection::tcpv4_ev (io_watcher &w, short revents) 207tcp_connection::tcpv4_ev (io_watcher &w, short revents)
168{ 208{
169 last_activity = NOW; 209 last_activity = NOW;
170 210
171 if (revents & (POLLERR | POLLHUP)) 211 if (revents & (POLLERR | POLLHUP))
212 {
172 error (); 213 error ();
173 else if (revents & POLLOUT && state == CONNECTING) 214 return;
174 { 215 }
216
217 if (revents & POLLOUT)
218 {
219 if (state == CONNECTING)
220 {
175 state = ESTABLISHED; 221 state = ESTABLISHED;
222 set (POLLIN);
223 }
224 else if (state == ESTABLISHED)
225 {
226 if (w_pkt)
227 {
228 if (write_packet ())
229 {
230 delete w_pkt; w_pkt = 0;
231
232 set (POLLIN);
233 }
234 }
235 else
236 set (POLLIN);
237 }
238 else
176 set (POLLIN); 239 set (POLLIN);
177 } 240 }
178 241
179 else if (revents & POLLIN) 242 if (revents & POLLIN)
180 { 243 {
181 for (;;) 244 for (;;)
182 { 245 {
183 if (!r_pkt) 246 if (!r_pkt)
184 { 247 {
211 r_pkt = 0; 274 r_pkt = 0;
212 275
213 continue; 276 continue;
214 } 277 }
215 } 278 }
216 279 else
280 break;
217 } 281 }
218 else if (len < 0 && (errno == EINTR || errno == EAGAIN)) 282 else if (len < 0 && (errno == EINTR || errno == EAGAIN))
219 return; 283 break;
220 284
221 error (); 285 error ();
222 return; 286 break;
223 } 287 }
224 } 288 }
225} 289}
226 290
227bool 291bool
248 close (fd); 312 close (fd);
249 } 313 }
250 } 314 }
251 else if (state == ESTABLISHED) 315 else if (state == ESTABLISHED)
252 { 316 {
317 // drop packet if the tcp write buffer is full. this *is* the
318 // right thing to do, not using tcp *is* the right thing to do.
319 if (!w_pkt)
320 {
253 // how this maps to the underlying tcp packet we don't know 321 // how this maps to the underlying tcp packets we don't know
254 // and we don't care. at least we tried ;) 322 // and we don't care. at least we tried ;)
255 setsockopt (fd, SOL_IP, IP_TOS, &tos, sizeof tos); 323 setsockopt (fd, SOL_IP, IP_TOS, &tos, sizeof tos);
256 324
257 // we use none of the advantages of tcp; if an error occurs, just drop 325 w_pkt = pkt;
258 // (this happens when a tcp connection gets stuck, too, which might not be 326 w_ofs = 0;
259 // the wisest thing to do.. either drop packet (too late) or make sure 327 w_len = pkt->len + 2; // length + size header
260 // it gets delivered)
261 u16 len = htons (pkt->len);
262 328
263 iovec vec[2]; 329 if (write_packet ())
264 vec[0].iov_base = &len; 330 w_pkt = 0;
265 vec[0].iov_len = sizeof len; 331 else
266 vec[1].iov_base = &((*pkt)[0]); 332 {
267 vec[1].iov_len = pkt->len; 333 w_pkt = new vpn_packet;
334 w_pkt->set (*pkt);
335
336 set (POLLIN | POLLOUT);
337 }
268 338 }
269 if (sizeof (u16) + pkt->len != writev (fd, vec, 2))
270 error ();
271 } 339 }
272 340
273 return state != ERROR; 341 return state != ERROR;
274} 342}
275 343
276tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_) 344tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_)
277: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev) 345: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev)
278{ 346{
279 last_activity = NOW; 347 last_activity = NOW;
280 r_pkt = 0; 348 r_pkt = 0;
349 w_pkt = 0;
281 fd = fd_; 350 fd = fd_;
282 351
283 if (fd < 0) 352 if (fd < 0)
284 { 353 {
285 active = true; 354 active = true;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines