--- deliantra/server/socket/loop.C 2006/12/13 02:55:51 1.10 +++ deliantra/server/socket/loop.C 2006/12/14 00:01:37 1.11 @@ -73,6 +73,7 @@ { const char *cmdname; func_uint8_int_ns cmdproc; + uint8 flag; }; typedef void (*func_uint8_int_pl) (char *, int, player *); @@ -109,22 +110,22 @@ {"mapredraw", MapRedrawCmd, 0}, /* Added: phil */ {"mapinfo", MapInfoCmd, 2}, /* CF+ */ {"ext", ExtCmd, 2}, /* CF+ */ - {NULL, NULL, 0} /* terminator */ + { 0 } /* terminator */ }; /** Face-related commands */ static struct NsCmdMapping nscommands[] = { - {"addme", AddMeCmd}, + {"addme", AddMeCmd, 2}, {"askface", SendFaceCmd}, /* Added: phil */ {"requestinfo", RequestInfo}, - {"setfacemode", SetFaceMode}, - {"setsound", SetSound}, - {"setup", SetUp}, - {"version", VersionCmd}, - {"toggleextendedinfos", ToggleExtendedInfos}, /*Added: tchize */ - {"toggleextendedtext", ToggleExtendedText}, /*Added: tchize */ + {"setfacemode", SetFaceMode, 2}, + {"setsound", SetSound, 2}, + {"setup", SetUp, 2}, + {"version", VersionCmd, 2}, + {"toggleextendedinfos", ToggleExtendedInfos, 2}, /*Added: tchize */ + {"toggleextendedtext", ToggleExtendedText, 2}, /*Added: tchize */ {"asksmooth", AskSmooth}, /*Added: tchize (smoothing technologies) */ - {NULL, NULL} /* terminator (I, II & III) */ + { 0 } /* terminator (I, II & III) */ }; /** @@ -182,68 +183,65 @@ */ void -HandleClient (NewSocket * ns, player *pl) +HandleClient (NewSocket *ns, player *pl) { - int len = 0, i, cnt; - char *data; - /* Loop through this - maybe we have several complete packets here. */ // limit to a few commands only, though, as to not monopolise the server - for (cnt = 16; cnt--;) + for (int repeat = 16; repeat--;) { /* If it is a player, and they don't have any speed left, we * return, and will read in the data when they do have time. */ - if (pl && pl->state == ST_PLAYING && pl->ob != NULL && pl->ob->speed_left < 0) - { - return; - } + if (pl && pl->state == ST_PLAYING && pl->ob && pl->ob->speed_left < 0) + return; - i = SockList_ReadPacket (ns->fd, &ns->inbuf, MAXSOCKBUF - 1); + int pkt_len = ns->read_packet (); - if (i < 0) + if (pkt_len < 0) { -#ifdef ESRV_DEBUG - LOG (llevDebug, "HandleClient: Read error on connection player %s\n", (pl ? pl->ob->name : "None")); -#endif + LOG (llevError, "read error on player %s\n", &pl->ob->name); /* Caller will take care of cleaning this up */ ns->status = Ns_Dead; return; } - /* Still dont have a full packet */ - if (i == 0) + else if (pkt_len == 0) + /* Still dont have a full packet */ return; -// //D//TODO//temporarily log long commands -// if (ns->inbuf.len >= 40 && pl && pl->ob) -// LOG (llevDebug, "HandleClient: long comamnd from <%s,%s> %d<%s>\n", pl->ob->name, ns->host, ns->inbuf.len, ns->inbuf.buf + 2); - /* First, break out beginning word. There are at least * a few commands that do not have any paremeters. If * we get such a command, don't worry about trying * to break it up. */ - data = (char *) strchr ((char *) ns->inbuf.buf + 2, ' '); + int datalen; + char *data = strchr ((char *)ns->inbuf + 2, ' '); + if (data) { - *data = '\0'; - data++; - len = ns->inbuf.len - (data - (char *) ns->inbuf.buf); + *data++ = 0; + datalen = pkt_len - (data - (char *)ns->inbuf); } else - len = 0; + { + data = (char *)ns->inbuf + 2; // better read garbage than segfault + datalen = 0; + } + + ns->inbuf [pkt_len] = 0; /* Terminate buffer - useful for string data */ - ns->inbuf.buf[ns->inbuf.len] = '\0'; /* Terminate buffer - useful for string data */ - for (i = 0; nscommands[i].cmdname != NULL; i++) + for (int i = 0; nscommands[i].cmdname; i++) { - if (strcmp ((char *) ns->inbuf.buf + 2, nscommands[i].cmdname) == 0) + if (!strcmp ((char *)ns->inbuf + 2, nscommands[i].cmdname)) { - nscommands[i].cmdproc ((char *) data, len, ns); - ns->inbuf.len = 0; - return; //D// not doing this causes random memory corruption - goto next_packet; + nscommands[i].cmdproc (data, datalen, ns); + ns->skip_packet (pkt_len); + //D// not doing this causes random memory corruption + if (nscommands[i].flag & 2) + goto next_packet; + return; } } + /* Player must be in the playing state or the flag on the * the command must be zero for the user to use the command - * otherwise, a player cam save, be in the play_again state, and @@ -252,24 +250,29 @@ * one they can't use, we still swallow it up. */ if (pl) - for (i = 0; plcommands[i].cmdname != NULL; i++) + for (int i = 0; plcommands[i].cmdname; i++) { - if (strcmp ((char *) ns->inbuf.buf + 2, plcommands[i].cmdname) == 0) + if (!strcmp ((char *)ns->inbuf + 2, plcommands[i].cmdname)) { if (pl->state == ST_PLAYING || !(plcommands[i].flag & 1)) - plcommands[i].cmdproc ((char *) data, len, pl); - ns->inbuf.len = 0; + plcommands[i].cmdproc ((char *) data, datalen, pl); + + ns->skip_packet (pkt_len); //D// not doing this causes random memory corruption if (plcommands[i].flag & 2) goto next_packet; + return; } } + + printf ("BP34n");//D /* If we get here, we didn't find a valid command. Logging * this might be questionable, because a broken client/malicious * user could certainly send a whole bunch of invalid commands. */ - LOG (llevDebug, "Bad command from client (%s)\n", ns->inbuf.buf + 2); + LOG (llevDebug, "Bad command from client (%s)\n", ns->inbuf + 2); + ns->skip_packet (pkt_len); next_packet: ; } @@ -482,7 +485,8 @@ if (init_sockets[i].status == Ns_Avail) continue; - if (FD_ISSET (init_sockets[i].fd, &tmp_read)) + //TODO: disassociate handleclient from socket readin + if (init_sockets[i].inbuf_len || FD_ISSET (init_sockets[i].fd, &tmp_read)) HandleClient (&init_sockets[i], NULL); if (FD_ISSET (init_sockets[i].fd, &tmp_write))