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.3 by pcg, Sun Apr 6 20:01:53 2003 UTC vs.
Revision 1.4 by pcg, Mon Apr 7 01:12:56 2003 UTC

43#include <fcntl.h> 43#include <fcntl.h>
44#include <sys/poll.h> 44#include <sys/poll.h>
45 45
46#include "vpn.h" 46#include "vpn.h"
47 47
48#if ENABLE_HTTP_PROXY
49# include "conf.h"
50#endif
51
48struct tcp_connection; 52struct tcp_connection;
49 53
50struct lt_sockinfo 54struct lt_sockinfo
51{ 55{
52 bool operator()(const sockinfo *a, const sockinfo *b) const 56 bool operator()(const sockinfo *a, const sockinfo *b) const
68struct tcp_connection : io_watcher { 72struct tcp_connection : io_watcher {
69 tstamp last_activity; 73 tstamp last_activity;
70 const sockinfo si; 74 const sockinfo si;
71 vpn &v; 75 vpn &v;
72 bool active; // this connection has been actively established 76 bool active; // this connection has been actively established
73 enum { ERROR, IDLE, CONNECTING, ESTABLISHED } state; 77 enum { ERROR, IDLE, CONNECTING, CONNECTING_PROXY, ESTABLISHED } state;
74 78
75 vpn_packet *r_pkt; 79 vpn_packet *r_pkt;
76 u32 r_len, r_ofs; 80 u32 r_len, r_ofs;
77 81
78 vpn_packet *w_pkt; 82 vpn_packet *w_pkt;
79 u32 w_len, w_ofs; 83 u32 w_len, w_ofs;
84
85#if ENABLE_HTTP_PROXY
86 char *proxy_req;
87 int proxy_req_len;
88#endif
80 89
81 void tcpv4_ev (io_watcher &w, short revents); 90 void tcpv4_ev (io_watcher &w, short revents);
82 91
83 bool send_packet (vpn_packet *pkt, int tos); 92 bool send_packet (vpn_packet *pkt, int tos);
84 bool write_packet (); 93 bool write_packet ();
150 i = info->second; 159 i = info->second;
151 160
152 return i->send_packet (pkt, tos); 161 return i->send_packet (pkt, tos);
153} 162}
154 163
155void tcp_connection::error ()
156{
157 if (fd >= 0)
158 {
159 close (fd);
160 fd = -1;
161 }
162
163 delete r_pkt; r_pkt = 0;
164 delete w_pkt; w_pkt = 0;
165
166 stop ();
167 state = active ? IDLE : ERROR;
168}
169
170bool 164bool
171tcp_connection::write_packet () 165tcp_connection::write_packet ()
172{ 166{
173 ssize_t len; 167 ssize_t len;
174 168
218 { 212 {
219 if (state == CONNECTING) 213 if (state == CONNECTING)
220 { 214 {
221 state = ESTABLISHED; 215 state = ESTABLISHED;
222 set (POLLIN); 216 set (POLLIN);
217#if ENABLE_HTTP_PROXY
218 if (::conf.proxy_host && ::conf.proxy_port)
219 {
220 state = CONNECTING_PROXY;
221 write (fd, proxy_req, proxy_req_len);
222 free (proxy_req); proxy_req = 0;
223 }
224#endif
223 } 225 }
224 else if (state == ESTABLISHED) 226 else if (state == ESTABLISHED)
225 { 227 {
226 if (w_pkt) 228 if (w_pkt)
227 { 229 {
239 set (POLLIN); 241 set (POLLIN);
240 } 242 }
241 243
242 if (revents & POLLIN) 244 if (revents & POLLIN)
243 { 245 {
246 if (state == ESTABLISHED)
244 for (;;) 247 for (;;)
245 { 248 {
246 if (!r_pkt) 249 if (!r_pkt)
247 { 250 {
248 r_pkt = new vpn_packet; 251 r_pkt = new vpn_packet;
249 r_ofs = 0; 252 r_ofs = 0;
250 r_len = 2; // header 253 r_len = 2; // header
251 } 254 }
252 255
253 ssize_t len = read (fd, &((*r_pkt)[r_ofs < 2 ? r_ofs : r_ofs - 2]), r_len); 256 ssize_t len = read (fd, &((*r_pkt)[r_ofs < 2 ? r_ofs : r_ofs - 2]), r_len);
254 257
255 if (len > 0) 258 if (len > 0)
256 { 259 {
257 r_len -= len; 260 r_len -= len;
258 r_ofs += len; 261 r_ofs += len;
259 262
260 if (r_len == 0) 263 if (r_len == 0)
264 {
265 if (r_ofs == 2)
266 {
267 r_len = ntohs (*(u16 *)&((*r_pkt)[0]));
268 r_pkt->len = r_len;
269
270 if (r_len > 0 && r_len < MAXSIZE)
271 continue;
272 }
273 else
274 {
275 v.recv_vpn_packet (r_pkt, si);
276 delete r_pkt;
277 r_pkt = 0;
278
279 continue;
280 }
281 }
282 else
283 break;
284 }
285 else if (len < 0 && (errno == EINTR || errno == EAGAIN))
286 break;
287
288 error ();
289 break;
290 }
291#if ENABLE_HTTP_PROXY
292 else if (state == CONNECTING_PROXY)
293 {
294 fcntl (fd, F_SETFL, 0);
295 char r[1024];
296 int i;
297 bool emptyline = false;
298
299 // we do a blocking read of the response, to hell with it
300 for (i = 0; i < 1023; i++)
301 {
302 int l = read (fd, &r[i], 1);
303
304 if (l <= 0)
261 { 305 {
262 if (r_ofs == 2) 306 error ();
263 { 307 return;
264 r_len = ntohs (*(u16 *)&((*r_pkt)[0]));
265 r_pkt->len = r_len;
266
267 if (r_len > 0 && r_len < MAXSIZE)
268 continue;
269 } 308 }
309
310 if (r[i] == '\012')
311 {
312 if (emptyline)
313 break;
270 else 314 else
271 {
272 v.recv_vpn_packet (r_pkt, si);
273 delete r_pkt;
274 r_pkt = 0;
275
276 continue; 315 emptyline = true;
277 } 316 }
317 else if (r[i] != '\015')
318 emptyline = false;
319 }
320
321 fcntl (fd, F_SETFL, O_NONBLOCK);
322
323 if (i < 12)
324 {
325 slog (L_ERR, _("unable to do proxy-forwarding, short response"));
326 error ();
327 }
328 else if (r[0] != 'H' || r[1] != 'T' || r[2] != 'T' || r[3] != 'P' || r[4] != '/'
329 || r[5] != '1' // http-major
330 || r[9] != '2') // response
331 {
332 slog (L_ERR, _("malformed or unexpected proxy response (%.12s)"), r);
333 error ();
334 }
335 else
336 state = ESTABLISHED;
337 }
338#endif
339 }
340}
341
342bool
343tcp_connection::send_packet (vpn_packet *pkt, int tos)
344{
345 last_activity = NOW;
346
347 if (state == IDLE)
348 {
349 // woaw, the first lost packet ;)
350 fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
351
352 if (fd >= 0)
353 {
354 const sockinfo *csi = &si;
355
356#if ENABLE_HTTP_PROXY
357 sockinfo psi;
358
359 if (::conf.proxy_host && ::conf.proxy_port)
360 {
361 psi.set (::conf.proxy_host, ::conf.proxy_port, PROT_TCPv4);
362
363 if (psi.valid ())
364 {
365 csi = &psi;
366
367 proxy_req_len = asprintf (&proxy_req,
368 "CONNECT %s:%d HTTP/1.0\015\012"
369 "%s%s%s" // optional proxy-auth
370 "\015\012",
371 si.ntoa (),
372 ntohs (si.port),
373 ::conf.proxy_auth ? "Proxy-Authorization: Basic " : "",
374 ::conf.proxy_auth ? ::conf.proxy_auth : "",
375 ::conf.proxy_auth ? "\015\012" : "");
376
278 } 377 }
279 else 378 else
280 break; 379 slog (L_ERR, _("unable to resolve http proxy hostname '%s', trying direct"),
380 ::conf.proxy_host);
381 }
382#endif
281 } 383
282 else if (len < 0 && (errno == EINTR || errno == EAGAIN))
283 break;
284
285 error ();
286 break;
287 }
288 }
289}
290
291bool
292tcp_connection::send_packet (vpn_packet *pkt, int tos)
293{
294 last_activity = NOW;
295
296 if (state == IDLE)
297 {
298 // woaw, the first lost packet ;)
299 fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
300
301 if (fd >= 0)
302 {
303 fcntl (fd, F_SETFL, O_NONBLOCK); 384 fcntl (fd, F_SETFL, O_NONBLOCK);
304 385
305 if (connect (fd, si.sav4 (), si.salenv4 ()) >= 0 386 if (connect (fd, csi->sav4 (), csi->salenv4 ()) >= 0
306 || errno == EINPROGRESS) 387 || errno == EINPROGRESS)
307 { 388 {
308 state = CONNECTING; 389 state = CONNECTING;
309 start (fd, POLLOUT); 390 start (fd, POLLOUT);
310 } 391 }
337 } 418 }
338 } 419 }
339 } 420 }
340 421
341 return state != ERROR; 422 return state != ERROR;
423}
424
425void tcp_connection::error ()
426{
427 if (fd >= 0)
428 {
429 close (fd);
430 fd = -1;
431 }
432
433 delete r_pkt; r_pkt = 0;
434 delete w_pkt; w_pkt = 0;
435#if ENABLE_HTTP_PROXY
436 free (proxy_req); proxy_req = 0;
437#endif
438
439 stop ();
440 state = active ? IDLE : ERROR;
342} 441}
343 442
344tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_) 443tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_)
345: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev) 444: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev)
346{ 445{
347 last_activity = NOW; 446 last_activity = NOW;
348 r_pkt = 0; 447 r_pkt = 0;
349 w_pkt = 0; 448 w_pkt = 0;
350 fd = fd_; 449 fd = fd_;
450#if ENABLE_HTTP_PROXY
451 proxy_req = 0;
452#endif
351 453
352 if (fd < 0) 454 if (fd < 0)
353 { 455 {
354 active = true; 456 active = true;
355 state = IDLE; 457 state = IDLE;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines