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.5 by pcg, Mon Apr 7 01:28: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, _("%s: unable to do proxy-forwarding, short response"),
326 (const char *)si);
327 error ();
328 }
329 else if (r[0] != 'H' || r[1] != 'T' || r[2] != 'T' || r[3] != 'P' || r[4] != '/'
330 || r[5] != '1' // http-major
331 || r[9] != '2') // response
332 {
333 slog (L_ERR, _("%s: malformed or unexpected proxy response (%.12s)"),
334 (const char *)si, r);
335 error ();
336 }
337 else
338 state = ESTABLISHED;
339 }
340#endif
341 }
342}
343
344bool
345tcp_connection::send_packet (vpn_packet *pkt, int tos)
346{
347 last_activity = NOW;
348
349 if (state == IDLE)
350 {
351 // woaw, the first lost packet ;)
352 fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
353
354 if (fd >= 0)
355 {
356 const sockinfo *csi = &si;
357
358#if ENABLE_HTTP_PROXY
359 sockinfo psi;
360
361 if (::conf.proxy_host && ::conf.proxy_port)
362 {
363 psi.set (::conf.proxy_host, ::conf.proxy_port, PROT_TCPv4);
364
365 if (psi.valid ())
366 {
367 csi = &psi;
368
369 proxy_req_len = asprintf (&proxy_req,
370 "CONNECT %s:%d HTTP/1.0\015\012"
371 "%s%s%s" // optional proxy-auth
372 "\015\012",
373 si.ntoa (),
374 ntohs (si.port),
375 ::conf.proxy_auth ? "Proxy-Authorization: Basic " : "",
376 ::conf.proxy_auth ? ::conf.proxy_auth : "",
377 ::conf.proxy_auth ? "\015\012" : "");
378
278 } 379 }
279 else 380 else
280 break; 381 slog (L_ERR, _("unable to resolve http proxy hostname '%s', trying direct"),
382 ::conf.proxy_host);
383 }
384#endif
281 } 385
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); 386 fcntl (fd, F_SETFL, O_NONBLOCK);
304 387
305 if (connect (fd, si.sav4 (), si.salenv4 ()) >= 0 388 if (connect (fd, csi->sav4 (), csi->salenv4 ()) >= 0
306 || errno == EINPROGRESS) 389 || errno == EINPROGRESS)
307 { 390 {
308 state = CONNECTING; 391 state = CONNECTING;
309 start (fd, POLLOUT); 392 start (fd, POLLOUT);
310 } 393 }
337 } 420 }
338 } 421 }
339 } 422 }
340 423
341 return state != ERROR; 424 return state != ERROR;
425}
426
427void tcp_connection::error ()
428{
429 if (fd >= 0)
430 {
431 close (fd);
432 fd = -1;
433 }
434
435 delete r_pkt; r_pkt = 0;
436 delete w_pkt; w_pkt = 0;
437#if ENABLE_HTTP_PROXY
438 free (proxy_req); proxy_req = 0;
439#endif
440
441 stop ();
442 state = active ? IDLE : ERROR;
342} 443}
343 444
344tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_) 445tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_)
345: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev) 446: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev)
346{ 447{
347 last_activity = NOW; 448 last_activity = NOW;
348 r_pkt = 0; 449 r_pkt = 0;
349 w_pkt = 0; 450 w_pkt = 0;
350 fd = fd_; 451 fd = fd_;
452#if ENABLE_HTTP_PROXY
453 proxy_req = 0;
454#endif
351 455
352 if (fd < 0) 456 if (fd < 0)
353 { 457 {
354 active = true; 458 active = true;
355 state = IDLE; 459 state = IDLE;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines