ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/socket/lowlevel.C
(Generate patch)

Comparing deliantra/server/socket/lowlevel.C (file contents):
Revision 1.87 by root, Tue Nov 6 03:45:17 2012 UTC vs.
Revision 1.90 by root, Thu Nov 8 02:28:21 2012 UTC

48 * 48 *
49 * When the socket is clear to write, and we have backlogged data, this 49 * When the socket is clear to write, and we have backlogged data, this
50 * is called to write it out. 50 * is called to write it out.
51 */ 51 */
52 52
53 // write a nop to the socket at least every IDLE_NOP seconds. 53 // write a nop to the socket at least every IDLE_PING seconds.
54 if (!outputbuffer.len) 54 if (!outputbuffer.len)
55 { 55 {
56 if (last_send + IDLE_PING <= NOW && pl && pl->active) 56 if (last_send + IDLE_PING <= NOW && pl && pl->active)
57 { 57 {
58 // this is a bit ugly, but map1a seems to be the only 58 // this is a bit ugly, but map1a seems to be the only
200{ 200{
201 return (!(pkt->flags & PF_PLAYER) || pl) 201 return (!(pkt->flags & PF_PLAYER) || pl)
202 && (!(pkt->flags & PF_PLAYING) || state == ST_PLAYING); 202 && (!(pkt->flags & PF_PLAYING) || state == ST_PLAYING);
203} 203}
204 204
205// HACK: some commands currently should be executed 205// HACK: some commands currently should be executed
206// even when the player is frozen. this hack detects 206// even when the player is frozen. this hack detects
207// those commands. it should be folded into may_execute, 207// those commands. it should be folded into may_execute,
208// but kept seperate to emphasise the hack aspect, i.e. 208// but kept seperate to emphasise the hack aspect, i.e.
209// do it better, then remove. 209// do it better, then remove.
210static bool 210static bool
343 socket_ev.poll (socket_ev.poll () & ~EV_WRITE); 343 socket_ev.poll (socket_ev.poll () & ~EV_WRITE);
344 } 344 }
345 345
346 if (revents & EV_READ) 346 if (revents & EV_READ)
347 { 347 {
348 //TODO: rate-limit tcp connection in better ways, important 348 int amount;
349 uint8 *rbuf;
349 350
351 if (ws_version)
352 {
353 if (ws_inbuf_len + 2048 > ws_inbuf_alloc)
354 ws_inbuf = (uint8 *)realloc (ws_inbuf, ws_inbuf_alloc += 4096);
355
356 rbuf = ws_inbuf;
357 amount = ws_inbuf_alloc - ws_inbuf_len;
358 }
359 else
360 {
361 rbuf = inbuf;
350 int amount = sizeof (inbuf) - inbuf_len; 362 amount = sizeof (inbuf) - inbuf_len;
363 }
351 364
352 if (!amount) 365 if (!amount)
353 { 366 {
354 // input buffer full 367 // input buffer full
355 LOG (llevError, "input buffer overflow."); 368 LOG (llevError, "input buffer overflow.");
356 destroy (); 369 destroy ();
357 return; 370 return;
358 } 371 }
359 372
373 amount = read (fd, ws_inbuf + ws_inbuf_len, amount);
374
375 if (!amount)
376 {
377 destroy ();
378 return;
379 }
380 else if (amount < 0)
381 {
382 if (errno != EAGAIN && errno != EINTR)
383 {
384 LOG (llevError, "read error: %s\n", strerror (errno));
385 destroy ();
386 return;
387 }
388
389 // should not be here, normally
390 }
391
360 if (ws_version) 392 if (ws_version)
361 { 393 {
362 if (ws_inbuf_len + 4096 > ws_inbuf_alloc) 394 ws_inbuf_len += amount;
363 ws_inbuf = (uint8 *)realloc (ws_inbuf, ws_inbuf_alloc += 4096);
364 395
365 int len = read (fd, ws_inbuf + ws_inbuf_len, ws_inbuf_alloc - ws_inbuf_len); 396 while (ws_inbuf_len)
366
367 if (len > 0)
368 { 397 {
369 ws_inbuf_len += len;
370
371 if (ws_inbuf_len < 2 + 4) // 6 is minimum length: op, len, mask 398 if (ws_inbuf_len < 2 + 4) // 6 is minimum length: op, len, mask
372 return; 399 break;
373 400
374 int d = 2; 401 int d = 2;
402 int fin = ws_inbuf [0] & 0x80;
375 int o = ws_inbuf [0] & 15; 403 int op = ws_inbuf [0] & 0x0f;
376 int l = ws_inbuf [1] & 127; 404 int len = ws_inbuf [1] & 0x7f;
377 405
378 if (l == 126) 406 if (len == 126)
379 { 407 {
380 l = (ws_inbuf [2] << 8) | ws_inbuf [3]; 408 len = (ws_inbuf [2] << 8) | ws_inbuf [3];
381 d += 2; 409 d += 2;
382 } 410 }
383 else if (l == 127) 411 else if (len == 127)
384 { 412 {
385 if (ws_inbuf_len < 2 + 8) 413 if (ws_inbuf_len < 2 + 8)
386 return; 414 return;
387 415
388 // we don't do extra long frames, if a browser wants to send >2**32 bytes, 416 // we don't do extra long frames, if a browser wants to send >2**32 bytes,
389 // there are bigger issues to fix. 417 // there are bigger issues to fix.
390 l = (ws_inbuf [6] << 24) 418 len = (ws_inbuf [8] << 8) | ws_inbuf [9];
391 | (ws_inbuf [7] << 16)
392 | (ws_inbuf [8] << 8)
393 | ws_inbuf [9];
394 d += 8; 419 d += 8;
395 } 420 }
396 421
397 // we only continue if we have a complete frame 422 // we only continue if we have a complete frame
398 if (ws_inbuf_len < d + 4 + l) 423 if (ws_inbuf_len < d + 4 + len)
399 return; 424 return;
400 425
401 switch (o) 426 switch (op)
402 { 427 {
403 case 0: o = ws_inbuf_type; break; // continuation 428 case 0: op = ws_inbuf_type; break; // continuation
404 case 1: ws_inbuf_type = 1; break; // utf-8 429 case 1: ws_inbuf_type = 1; break; // utf-8
405 case 2: ws_inbuf_type = 2; break; // binary 430 case 2: ws_inbuf_type = 2; break; // binary
406 } 431 }
407 432
408 if (l > amount) 433 if (len > sizeof (inbuf) - inbuf_len)
409 { 434 {
410 // input buffer full 435 // input buffer full
411 LOG (llevError, "input buffer overflow (ws)."); 436 LOG (llevError, "input buffer overflow (ws).");
412 destroy (); 437 destroy ();
413 return; 438 return;
414 } 439 }
415 440
441 uint8 *buf = inbuf + inbuf_len + 2;
442
416 for (int i = 0; i < l; ++i) 443 for (int i = 0; i < len; ++i)
417 inbuf [inbuf_len + i] = ws_inbuf [d + 4 + i] ^ ws_inbuf [d + (i & 3)]; 444 buf [i] = ws_inbuf [d + 4 + i] ^ ws_inbuf [d + (i & 3)];
418 445
419 // remove frame 446 // remove frame
420 ws_inbuf_len -= d + 4 + l; 447 ws_inbuf_len -= d + 4 + len;
421 memmove (ws_inbuf, ws_inbuf + d + 4 + l, ws_inbuf_len); 448 memmove (ws_inbuf, ws_inbuf + d + 4 + len, ws_inbuf_len);
422 449
423 switch (o) 450 switch (op)
424 { 451 {
425 case 1: // utf-8 452 case 1: // utf-8
453 // utf-8 encoded frames cannot have full length (MAXSOCKBUF) in all cases
454 // but we assume that these extra-long packets will be rare.
426 //TODO 455 {
456 uint8 *a = buf;
457 uint8 *b = a;
458 uint8 *c = a + len;
459
460 for (; a < c; ++a, ++b)
461 {
462 *b = *a;
463
464 if (*a >= 0x80)
465 *b = (a [0] & 0x1f) << 6 | (a [1] & 0x3f), ++a;
466 }
467
468 len -= a - b;
469 }
470 /* FALLTHROUGH */
471 case 2: // binary
472 inbuf_len += len;
473
474 if (fin)
475 {
476 inbuf [0] = inbuf_len >> 8;
477 inbuf [1] = inbuf_len;
478
479 inbuf_len += 2;
480
481 inbuf_handle ();
482 }
427 break; 483 break;
428 case 2: // binary
429 break;
430 484
431 case 9: // ping 485 case 9: // ping
432 { 486 {
433 // send pong - we assume ping messages are <64k 487 // send pong - we assume ping messages are <64k
434 // as we can't handle >10k at the moment anyway. 488 // as we can't handle >10k at the moment anyway.
435 uint8 hdr [] = { 0x8a, 126, l >> 8, l }; 489 uint8 hdr [] = { 0x8a, 126, len >> 8, len };
436 send (hdr, sizeof (hdr)); 490 send (hdr, sizeof (hdr));
437 send (inbuf + inbuf_len, l); 491 send (inbuf + inbuf_len, len);
438 } 492 }
439 return; 493 break;
440 494
441 case 10: // pong 495 case 10: // pong
442 return; 496 break;
443 497
444 case 8: // close 498 case 8: // close
445 default: 499 default:
446 destroy (); 500 destroy ();
447 return; 501 return;
448 } 502 }
449
450 amount = l;
451 } 503 }
452 else
453 amount = -1;
454 }
455 else
456 amount = read (fd, inbuf + inbuf_len, amount);
457
458 if (!amount)
459 {
460 destroy ();
461 return;
462 }
463 else if (amount < 0)
464 {
465 if (errno != EAGAIN && errno != EINTR)
466 {
467 LOG (llevError, "read error: %s\n", strerror (errno));
468 destroy ();
469 return;
470 }
471
472 // should not be here, normally
473 } 504 }
474 else 505 else
475 { 506 {
476 inbuf_len += amount; 507 inbuf_len += amount;
477 inbuf_handle (); 508 inbuf_handle ();
554 if (!sl.length ()) 585 if (!sl.length ())
555 return; 586 return;
556 587
557 if (ws_version == 8) 588 if (ws_version == 8)
558 { 589 {
559 uint8 hdr [4] = { 0x81, 126, sl.length () >> 8, sl.length () }; 590 static uint8 buf [MAXSOCKBUF * 2 + 4];
560 // TODO: utf-8 encoding 591
561 send (hdr, 4); 592 uint8 *b = buf + 4;
562 send (sl.buf_ + sl.hdrlen, sl.cur - sl.buf_ - sl.hdrlen); 593 for (uint8 *a = sl.buf_ + sl.hdrlen; a < sl.cur; ++a)
594 {
595 if (*a < 0x80)
596 *b++ = *a;
597 else
598 {
599 *b++ = 0xc0 | ((*a >> 6) & 0x1f);
600 *b++ = 0x80 | ( *a & 0x3f);
601 }
602 }
603
604 assert (b - buf < sizeof (buf));
605
606 int len = b - (buf + 4);
607
608 if (len < 126)
609 {
610 buf [2] = 0x81;
611 buf [3] = len;
612
613 send (buf + 2, len + 2);
614 }
615 else
616 {
617 buf [0] = 0x81;
618 buf [1] = 126;
619 buf [2] = len >> 8;
620 buf [3] = len;
621
622 send (buf, len + 4);
623 }
563 } 624 }
564 else if (ws_version == 13) 625 else if (ws_version == 13)
565 { 626 {
627 int len = sl.length ();
628
629 if (len < 126)
630 {
631 uint8 hdr [] = { 0x82, len };
632 send (hdr, sizeof (hdr));
633 }
634 else
635 {
566 uint8 hdr [4] = { 0x82, 126, sl.length () >> 8, sl.length () }; 636 uint8 hdr [] = { 0x82, 126, len >> 8, len };
567 send (hdr, 4); 637 send (hdr, sizeof (hdr));
638 }
639
568 send (sl.buf_ + sl.hdrlen, sl.cur - sl.buf_ - sl.hdrlen); 640 send (sl.buf_ + sl.hdrlen, len);
569 } 641 }
570 else 642 else
571 { 643 {
572 assert (sl.hdrlen == 2); 644 assert (sl.hdrlen == 2);
573 645

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines