--- deliantra/server/socket/lowlevel.C 2012/11/06 21:50:36 1.89 +++ deliantra/server/socket/lowlevel.C 2012/11/15 04:50:50 1.92 @@ -50,7 +50,7 @@ * is called to write it out. */ - // write a nop to the socket at least every IDLE_NOP seconds. + // write a nop to the socket at least every IDLE_PING seconds. if (!outputbuffer.len) { if (last_send + IDLE_PING <= NOW && pl && pl->active) @@ -169,8 +169,7 @@ * Dispatch table for the server. */ static struct packet_type packets[] = { - {"ncom", PC(NewPlayerCmd) PF_PLAYING | PF_COMMAND6 }, - {"command", PC(PlayerCmd) PF_PLAYING | PF_COMMAND0 }, + {"command", PC(PlayerCmd) PF_PLAYING | PF_COMMAND }, {"examine", PC(ExamineCmd) PF_PLAYING }, {"ex", PC(ExCmd) PF_PLAYING }, @@ -210,18 +209,12 @@ static bool always_immediate (const client *ns, const packet_type *pkt, const char *data, int len) { - if (!(pkt->flags & (PF_COMMAND0 | PF_COMMAND6))) + if (!(pkt->flags & PF_COMMAND)) return false; if (!ns->pl || !ns->pl->ob || !ns->pl->ob->map) return false; - if (pkt->flags & PF_COMMAND6) - { - data += 6; - len -= 6; - } - if (len > 4 && data [ 3] == ' ' && !strncmp (data, "say " , 4)) return true; if (len > 5 && data [ 4] == ' ' && !strncmp (data, "chat " , 5)) return true; if (len > 6 && data [ 5] == ' ' && !strncmp (data, "shout " , 6)) return true; @@ -345,9 +338,22 @@ if (revents & EV_READ) { - //TODO: rate-limit tcp connection in better ways, important + int amount; + uint8 *rbuf; + + if (ws_version) + { + if (ws_inbuf_len + 2048 > ws_inbuf_alloc) + ws_inbuf = (uint8 *)realloc (ws_inbuf, ws_inbuf_alloc += 4096); - int amount = sizeof (inbuf) - inbuf_len; + rbuf = ws_inbuf + ws_inbuf_len; + amount = ws_inbuf_alloc - ws_inbuf_len; + } + else + { + rbuf = inbuf + inbuf_len; + amount = sizeof (inbuf) - inbuf_len; + } if (!amount) { @@ -357,55 +363,67 @@ return; } - if (ws_version) + amount = read (fd, rbuf, amount); + + if (!amount) { - if (ws_inbuf_len + 2048 > ws_inbuf_alloc) - ws_inbuf = (uint8 *)realloc (ws_inbuf, ws_inbuf_alloc += 4096); + destroy (); + return; + } + else if (amount < 0) + { + if (errno != EAGAIN && errno != EINTR) + { + LOG (llevError, "read error: %s\n", strerror (errno)); + destroy (); + return; + } - int len = read (fd, ws_inbuf + ws_inbuf_len, ws_inbuf_alloc - ws_inbuf_len); + // should not be here, normally + } - if (len > 0) - { - ws_inbuf_len += len; + if (ws_version) + { + ws_inbuf_len += amount; + while (ws_inbuf_len) + { if (ws_inbuf_len < 2 + 4) // 6 is minimum length: op, len, mask - return; + break; - int d = 2; - int o = ws_inbuf [0] & 15; - int l = ws_inbuf [1] & 127; + int d = 2; + int fin = ws_inbuf [0] & 0x80; + int op = ws_inbuf [0] & 0x0f; + int len = ws_inbuf [1] & 0x7f; - if (l == 126) + if (len == 126) { - l = (ws_inbuf [2] << 8) | ws_inbuf [3]; + len = (ws_inbuf [2] << 8) | ws_inbuf [3]; d += 2; } - else if (l == 127) + else if (len == 127) { if (ws_inbuf_len < 2 + 8) return; // we don't do extra long frames, if a browser wants to send >2**32 bytes, // there are bigger issues to fix. - l = (ws_inbuf [6] << 24) - | (ws_inbuf [7] << 16) - | (ws_inbuf [8] << 8) - | ws_inbuf [9]; + len = (ws_inbuf [8] << 8) | ws_inbuf [9]; d += 8; } // we only continue if we have a complete frame - if (ws_inbuf_len < d + 4 + l) + if (ws_inbuf_len < d + 4 + len) return; - switch (o) + switch (op) { - case 0: o = ws_inbuf_type; break; // continuation - case 1: ws_inbuf_type = 1; break; // utf-8 - case 2: ws_inbuf_type = 2; break; // binary + case 0: op = ws_inbuf_type; break; // continuation + case 1: ws_inbuf_type = 1; break; // utf-8 + case 2: ws_inbuf_type = 2; break; // binary } - if (l > amount) + if (len > sizeof (inbuf) - inbuf_len) { // input buffer full LOG (llevError, "input buffer overflow (ws)."); @@ -413,20 +431,24 @@ return; } - for (int i = 0; i < l; ++i) - inbuf [inbuf_len + i] = ws_inbuf [d + 4 + i] ^ ws_inbuf [d + (i & 3)]; + uint8 *buf = inbuf + inbuf_len + 2; + + for (int i = 0; i < len; ++i) + buf [i] = ws_inbuf [d + 4 + i] ^ ws_inbuf [d + (i & 3)]; // remove frame - ws_inbuf_len -= d + 4 + l; - memmove (ws_inbuf, ws_inbuf + d + 4 + l, ws_inbuf_len); + ws_inbuf_len -= d + 4 + len; + memmove (ws_inbuf, ws_inbuf + d + 4 + len, ws_inbuf_len); - switch (o) + switch (op) { case 1: // utf-8 + // utf-8 encoded frames cannot have full length (MAXSOCKBUF) in all cases + // but we assume that these extra-long packets will be rare. { - uint8 *a = inbuf + inbuf_len; + uint8 *a = buf; uint8 *b = a; - uint8 *c = a + l; + uint8 *c = a + len; for (; a < c; ++a, ++b) { @@ -436,54 +458,42 @@ *b = (a [0] & 0x1f) << 6 | (a [1] & 0x3f), ++a; } - l -= a - b; + len -= a - b; } - break; + /* FALLTHROUGH */ case 2: // binary + inbuf_len += len; + + if (fin) + { + inbuf [0] = inbuf_len >> 8; + inbuf [1] = inbuf_len; + + inbuf_len += 2; + + inbuf_handle (); + } break; - case 9: // ping + case 9: // ping { // send pong - we assume ping messages are <64k // as we can't handle >10k at the moment anyway. - uint8 hdr [] = { 0x8a, 126, l >> 8, l }; + uint8 hdr [] = { 0x8a, 126, len >> 8, len }; send (hdr, sizeof (hdr)); - send (inbuf + inbuf_len, l); + send (inbuf + inbuf_len, len); } - return; + break; case 10: // pong - return; + break; case 8: // close default: destroy (); return; } - - amount = l; } - else - amount = -1; - } - else - amount = read (fd, inbuf + inbuf_len, amount); - - if (!amount) - { - destroy (); - return; - } - else if (amount < 0) - { - if (errno != EAGAIN && errno != EINTR) - { - LOG (llevError, "read error: %s\n", strerror (errno)); - destroy (); - return; - } - - // should not be here, normally } else { @@ -586,41 +596,41 @@ assert (b - buf < sizeof (buf)); - int l = b - (buf + 4); + int len = b - (buf + 4); - if (l < 126) + if (len < 126) { buf [2] = 0x81; - buf [3] = l; + buf [3] = len; - send (buf + 2, l + 2); + send (buf + 2, len + 2); } else { buf [0] = 0x81; buf [1] = 126; - buf [2] = l >> 8; - buf [3] = l; + buf [2] = len >> 8; + buf [3] = len; - send (buf, l + 4); + send (buf, len + 4); } } else if (ws_version == 13) { - int l = sl.length (); + int len = sl.length (); - if (l < 126) + if (len < 126) { - uint8 hdr [] = { 0x82, l }; + uint8 hdr [] = { 0x82, len }; send (hdr, sizeof (hdr)); } else { - uint8 hdr [] = { 0x82, 126, l >> 8, l }; + uint8 hdr [] = { 0x82, 126, len >> 8, len }; send (hdr, sizeof (hdr)); } - send (sl.buf_ + sl.hdrlen, l); + send (sl.buf_ + sl.hdrlen, len); } else {