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.7 by pcg, Tue Oct 14 03:22:09 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
175 if (w_ofs < 2) 169 if (w_ofs < 2)
176 { 170 {
177 u16 plen = htons (w_pkt->len); 171 u16 plen = htons (w_pkt->len);
178 172
179 iovec vec[2]; 173 iovec vec[2];
174 //TODO: char* is the right type? hardly...
180 vec[0].iov_base = ((u8 *)&plen) + w_ofs; 175 vec[0].iov_base = (char *)((u8 *)&plen) + w_ofs;
181 vec[0].iov_len = 2 - w_ofs; 176 vec[0].iov_len = 2 - w_ofs;
182 vec[1].iov_base = &((*w_pkt)[0]); 177 vec[1].iov_base = (char *)&((*w_pkt)[0]);
183 vec[1].iov_len = w_len - 2; 178 vec[1].iov_len = w_len - 2;
184 179
185 len = writev (fd, vec, 2); 180 len = writev (fd, vec, 2);
186 } 181 }
187 else 182 else
218 { 213 {
219 if (state == CONNECTING) 214 if (state == CONNECTING)
220 { 215 {
221 state = ESTABLISHED; 216 state = ESTABLISHED;
222 set (POLLIN); 217 set (POLLIN);
218#if ENABLE_HTTP_PROXY
219 if (::conf.proxy_host && ::conf.proxy_port)
220 {
221 state = CONNECTING_PROXY;
222 write (fd, proxy_req, proxy_req_len);
223 free (proxy_req); proxy_req = 0;
224 }
225#endif
223 } 226 }
224 else if (state == ESTABLISHED) 227 else if (state == ESTABLISHED)
225 { 228 {
226 if (w_pkt) 229 if (w_pkt)
227 { 230 {
239 set (POLLIN); 242 set (POLLIN);
240 } 243 }
241 244
242 if (revents & POLLIN) 245 if (revents & POLLIN)
243 { 246 {
247 if (state == ESTABLISHED)
244 for (;;) 248 for (;;)
245 { 249 {
246 if (!r_pkt) 250 if (!r_pkt)
247 { 251 {
248 r_pkt = new vpn_packet; 252 r_pkt = new vpn_packet;
249 r_ofs = 0; 253 r_ofs = 0;
250 r_len = 2; // header 254 r_len = 2; // header
251 } 255 }
252 256
253 ssize_t len = read (fd, &((*r_pkt)[r_ofs < 2 ? r_ofs : r_ofs - 2]), r_len); 257 ssize_t len = read (fd, &((*r_pkt)[r_ofs < 2 ? r_ofs : r_ofs - 2]), r_len);
254 258
255 if (len > 0) 259 if (len > 0)
256 { 260 {
257 r_len -= len; 261 r_len -= len;
258 r_ofs += len; 262 r_ofs += len;
259 263
260 if (r_len == 0) 264 if (r_len == 0)
265 {
266 if (r_ofs == 2)
267 {
268 r_len = ntohs (*(u16 *)&((*r_pkt)[0]));
269 r_pkt->len = r_len;
270
271 if (r_len > 0 && r_len < MAXSIZE)
272 continue;
273 }
274 else
275 {
276 v.recv_vpn_packet (r_pkt, si);
277 delete r_pkt;
278 r_pkt = 0;
279
280 continue;
281 }
282 }
283 else
284 break;
285 }
286 else if (len < 0 && (errno == EINTR || errno == EAGAIN))
287 break;
288
289 error ();
290 break;
291 }
292#if ENABLE_HTTP_PROXY
293 else if (state == CONNECTING_PROXY)
294 {
295 fcntl (fd, F_SETFL, 0);
296 char r[1024];
297 int i;
298 bool emptyline = false;
299
300 // we do a blocking read of the response, to hell with it
301 for (i = 0; i < 1023; i++)
302 {
303 int l = read (fd, &r[i], 1);
304
305 if (l <= 0)
261 { 306 {
262 if (r_ofs == 2) 307 error ();
263 { 308 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 } 309 }
310
311 if (r[i] == '\012')
312 {
313 if (emptyline)
314 break;
270 else 315 else
271 {
272 v.recv_vpn_packet (r_pkt, si);
273 delete r_pkt;
274 r_pkt = 0;
275
276 continue; 316 emptyline = true;
277 } 317 }
318 else if (r[i] != '\015')
319 emptyline = false;
320 }
321
322 fcntl (fd, F_SETFL, O_NONBLOCK);
323
324 if (i < 12)
325 {
326 slog (L_ERR, _("(%s): unable to do proxy-forwarding, short response"),
327 (const char *)si);
328 error ();
329 }
330 else if (r[0] != 'H' || r[1] != 'T' || r[2] != 'T' || r[3] != 'P' || r[4] != '/'
331 || r[5] != '1' // http-major
332 || r[9] != '2') // response
333 {
334 slog (L_ERR, _("(%s): malformed or unexpected proxy response (%.12s)"),
335 (const char *)si, r);
336 error ();
337 }
338 else
339 state = ESTABLISHED;
340 }
341#endif
342 }
343}
344
345bool
346tcp_connection::send_packet (vpn_packet *pkt, int tos)
347{
348 last_activity = NOW;
349
350 if (state == IDLE)
351 {
352 // woaw, the first lost packet ;)
353 fd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
354
355 if (fd >= 0)
356 {
357 const sockinfo *csi = &si;
358
359#if ENABLE_HTTP_PROXY
360 sockinfo psi;
361
362 if (::conf.proxy_host && ::conf.proxy_port)
363 {
364 psi.set (::conf.proxy_host, ::conf.proxy_port, PROT_TCPv4);
365
366 if (psi.valid ())
367 {
368 csi = &psi;
369
370 proxy_req_len = asprintf (&proxy_req,
371 "CONNECT %s:%d HTTP/1.0\015\012"
372 "%s%s%s" // optional proxy-auth
373 "\015\012",
374 si.ntoa (),
375 ntohs (si.port),
376 ::conf.proxy_auth ? "Proxy-Authorization: Basic " : "",
377 ::conf.proxy_auth ? ::conf.proxy_auth : "",
378 ::conf.proxy_auth ? "\015\012" : "");
379
278 } 380 }
279 else 381 else
280 break; 382 slog (L_ERR, _("unable to resolve http proxy hostname '%s', trying direct"),
383 ::conf.proxy_host);
384 }
385#endif
281 } 386
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); 387 fcntl (fd, F_SETFL, O_NONBLOCK);
304 388
305 if (connect (fd, si.sav4 (), si.salenv4 ()) >= 0 389 if (connect (fd, csi->sav4 (), csi->salenv4 ()) >= 0
306 || errno == EINPROGRESS) 390 || errno == EINPROGRESS)
307 { 391 {
308 state = CONNECTING; 392 state = CONNECTING;
309 start (fd, POLLOUT); 393 start (fd, POLLOUT);
310 } 394 }
318 // right thing to do, not using tcp *is* the right thing to do. 402 // right thing to do, not using tcp *is* the right thing to do.
319 if (!w_pkt) 403 if (!w_pkt)
320 { 404 {
321 // how this maps to the underlying tcp packets we don't know 405 // how this maps to the underlying tcp packets we don't know
322 // and we don't care. at least we tried ;) 406 // and we don't care. at least we tried ;)
407#if defined(SOL_IP) && defined(IP_TOS)
323 setsockopt (fd, SOL_IP, IP_TOS, &tos, sizeof tos); 408 setsockopt (fd, SOL_IP, IP_TOS, &tos, sizeof tos);
409#endif
324 410
325 w_pkt = pkt; 411 w_pkt = pkt;
326 w_ofs = 0; 412 w_ofs = 0;
327 w_len = pkt->len + 2; // length + size header 413 w_len = pkt->len + 2; // length + size header
328 414
337 } 423 }
338 } 424 }
339 } 425 }
340 426
341 return state != ERROR; 427 return state != ERROR;
428}
429
430void tcp_connection::error ()
431{
432 if (fd >= 0)
433 {
434 close (fd);
435 fd = -1;
436 }
437
438 delete r_pkt; r_pkt = 0;
439 delete w_pkt; w_pkt = 0;
440#if ENABLE_HTTP_PROXY
441 free (proxy_req); proxy_req = 0;
442#endif
443
444 stop ();
445 state = active ? IDLE : ERROR;
342} 446}
343 447
344tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_) 448tcp_connection::tcp_connection (int fd_, const sockinfo &si_, vpn &v_)
345: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev) 449: v(v_), si(si_), io_watcher(this, &tcp_connection::tcpv4_ev)
346{ 450{
347 last_activity = NOW; 451 last_activity = NOW;
348 r_pkt = 0; 452 r_pkt = 0;
349 w_pkt = 0; 453 w_pkt = 0;
350 fd = fd_; 454 fd = fd_;
455#if ENABLE_HTTP_PROXY
456 proxy_req = 0;
457#endif
351 458
352 if (fd < 0) 459 if (fd < 0)
353 { 460 {
354 active = true; 461 active = true;
355 state = IDLE; 462 state = IDLE;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines