--- deliantra/server/socket/image.C 2006/09/10 13:43:33 1.3 +++ deliantra/server/socket/image.C 2007/03/01 12:28:17 1.22 @@ -1,32 +1,27 @@ - /* - * static char *rcsid_init_c = - * "$Id: image.C,v 1.3 2006/09/10 13:43:33 root Exp $"; + * CrossFire, A Multiplayer game + * + * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team + * Copyright (C) 2001 Mark Wedel + * Copyright (C) 1992 Frank Tore Johansen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * The author can be reached via e-mail to */ -/* - CrossFire, A Multiplayer game for X-windows - - Copyright (C) 2001 Mark Wedel - Copyright (C) 1992 Frank Tore Johansen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - The author can be reached via e-mail to crossfire-devel@real-time.com -*/ - /** \file * Image related communication * @@ -41,27 +36,21 @@ #include #include -#include -#include -#include +#include "crc.h" #define MAX_FACE_SETS 20 /**< Maximum number of image sets the program will handle */ /** Information about one image */ typedef struct FaceInfo { - uint8 *data; /**< image data */ - uint16 datalen; /**< length of the xpm data */ - uint32 checksum; /**< Checksum of face data */ } FaceInfo; /** Information about one face set */ typedef struct { - char *prefix; /**< */ char *fullname; @@ -102,6 +91,7 @@ for (q = 0; q < nrofpixmaps; q++) if (facesets[num].faces[q].data) free (facesets[num].faces[q].data); + free (facesets[num].prefix); free (facesets[num].fullname); free (facesets[num].size); @@ -141,8 +131,10 @@ LOG (llevError, "get_face_fallback called with unused set (%d)?\n", faceset); return 0; /* use default set */ } + if (facesets[faceset].faces[imageno].data) return faceset; + return get_face_fallback (facesets[faceset].fallback, imageno); } @@ -168,12 +160,14 @@ LOG (llevError, "Face set %d falls to non set faceset %d\n", faceset, fallback); abort (); } + togo--; if (togo == 0) { LOG (llevError, "Infinite loop found in facesets. aborting.\n"); abort (); } + check_faceset_fallback (fallback, togo); } @@ -195,7 +189,6 @@ * it is just data it needs to allocate. As such, the code is written * to do such. */ - void read_client_images (void) { @@ -212,23 +205,23 @@ LOG (llevError, "Unable to open %s\n", filename); abort (); } + while (fgets (buf, HUGE_BUF - 1, infile) != NULL) { badline = 0; if (buf[0] == '#') continue; + if (!(cps[0] = strtok (buf, ":"))) badline = 1; + for (i = 1; i < 7; i++) - { - if (!(cps[i] = strtok (NULL, ":"))) - badline = 1; - } + if (!(cps[i] = strtok (NULL, ":"))) + badline = 1; + if (badline) - { - LOG (llevError, "Bad line in image_info file, ignoring line:\n %s", buf); - } + LOG (llevError, "Bad line in image_info file, ignoring line:\n %s", buf); else { len = atoi (cps[0]); @@ -237,20 +230,23 @@ LOG (llevError, "To high a setnum in image_info file: %d > %d\n", len, MAX_FACE_SETS); abort (); } - facesets[len].prefix = strdup_local (cps[1]); - facesets[len].fullname = strdup_local (cps[2]); + facesets[len].prefix = strdup (cps[1]); + facesets[len].fullname = strdup (cps[2]); facesets[len].fallback = atoi (cps[3]); - facesets[len].size = strdup_local (cps[4]); - facesets[len].extension = strdup_local (cps[5]); - facesets[len].comment = strdup_local (cps[6]); + facesets[len].size = strdup (cps[4]); + facesets[len].extension = strdup (cps[5]); + facesets[len].comment = strdup (cps[6]); } } + close_and_delete (infile, compressed); + for (i = 0; i < MAX_FACE_SETS; i++) { if (facesets[i].prefix) check_faceset_fallback (i, MAX_FACE_SETS); } + /* Loaded the faceset information - now need to load up the * actual faces. */ @@ -260,6 +256,7 @@ /* if prefix is not set, this is not used */ if (!facesets[fileno].prefix) continue; + facesets[fileno].faces = (FaceInfo *) calloc (nrofpixmaps, sizeof (FaceInfo)); sprintf (filename, "%s/crossfire.%d", settings.datadir, fileno); @@ -270,6 +267,7 @@ LOG (llevError, "Unable to open %s\n", filename); abort (); } + while (fgets (buf, HUGE_BUF - 1, infile) != NULL) { if (strncmp (buf, "IMAGE ", 6) != 0) @@ -277,21 +275,26 @@ LOG (llevError, "read_client_images:Bad image line - not IMAGE, instead\n%s", buf); abort (); } + num = atoi (buf + 6); if (num < 0 || num >= nrofpixmaps) { LOG (llevError, "read_client_images: Image num %d not in 0..%d\n%s", num, nrofpixmaps, buf); abort (); } + /* Skip accross the number data */ - for (cp = buf + 6; *cp != ' '; cp++); + for (cp = buf + 6; *cp != ' '; cp++) + ; + len = atoi (cp); if (len == 0 || len > MAX_IMAGE_SIZE) { LOG (llevError, "read_client_images: length not valid: %d > %d \n%s", len, MAX_IMAGE_SIZE, buf); abort (); } - /* We don't actualy care about the name if the image that + + /* We don't actualy care about the name of the image that * is embedded in the image file, so just ignore it. */ facesets[fileno].faces[num].datalen = len; @@ -301,14 +304,15 @@ LOG (llevError, "read_client_images: Did not read desired amount of data, wanted %d, got %d\n%s", len, i, buf); abort (); } - facesets[fileno].faces[num].checksum = 0; + + crc32 chksum; + for (i = 0; i < len; i++) - { - ROTATE_RIGHT (facesets[fileno].faces[num].checksum); - facesets[fileno].faces[num].checksum += facesets[fileno].faces[num].data[i]; - facesets[fileno].faces[num].checksum &= 0xffffffff; - } + chksum (facesets[fileno].faces[num].data[i]); + + facesets[fileno].faces[num].checksum = chksum; } + close_and_delete (infile, compressed); } /* For fileno < MAX_FACE_SETS */ } @@ -318,30 +322,18 @@ * the caching attribute. * */ - void -SetFaceMode (char *buf, int len, NewSocket * ns) +SetFaceMode (char *buf, int len, client *ns) { - char tmp[256]; - int mask = (atoi (buf) & CF_FACE_CACHE), mode = (atoi (buf) & ~CF_FACE_CACHE); if (mode == CF_FACE_NONE) - { - ns->facecache = 1; - } + ns->facecache = 1; else if (mode != CF_FACE_PNG) - { - sprintf (tmp, "drawinfo %d %s", NDI_RED, "Warning - send unsupported face mode. Will use Png"); - Write_String_To_Socket (ns, tmp, strlen (tmp)); -#ifdef ESRV_DEBUG - LOG (llevDebug, "SetFaceMode: Invalid mode from client: %d\n", mode); -#endif - } + ns->send_packet_printf ("drawinfo %d %s", NDI_RED, "Warning - send unsupported face mode. Will use Png"); + if (mask) - { - ns->facecache = 1; - } + ns->facecache = 1; } /** @@ -349,12 +341,10 @@ * This will be called often if the client is * caching images. */ - void -SendFaceCmd (char *buff, int len, NewSocket * ns) +SendFaceCmd (char *buf, int len, client *ns) { - long tmpnum = atoi (buff); - short facenum = tmpnum & 0xffff; + uint16 facenum = atoi (buf); if (facenum != 0) esrv_send_face (ns, facenum, 1); @@ -368,11 +358,9 @@ * face (and askface is the only place that should be setting it). Otherwise, * we look at the facecache, and if set, send the image name. */ - void -esrv_send_face (NewSocket * ns, short face_num, int nocache) +esrv_send_face (client *ns, short face_num, int nocache) { - SockList sl; char fallback; if (face_num <= 0 || face_num >= nrofpixmaps) @@ -381,7 +369,7 @@ return; } - sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + packet sl; fallback = get_face_fallback (ns->faceset, face_num); if (facesets[fallback].faces[face_num].data == NULL) @@ -392,40 +380,32 @@ if (ns->facecache && !nocache) { - if (ns->image2) - strcpy ((char *) sl.buf, "face2 "); - else if (ns->sc_version >= 1026) - strcpy ((char *) sl.buf, "face1 "); - else - strcpy ((char *) sl.buf, "face "); + sl << (ns->image2 ? "face2 " : "face1 ") + << uint16 (face_num); - sl.len = strlen ((const char *) sl.buf); - SockList_AddShort (&sl, face_num); if (ns->image2) - SockList_AddChar (&sl, fallback); - if (ns->sc_version >= 1026) - SockList_AddInt (&sl, facesets[fallback].faces[face_num].checksum); - strcpy ((char *) sl.buf + sl.len, new_faces[face_num].name); - sl.len += strlen (new_faces[face_num].name); - Send_With_Handling (ns, &sl); + sl << uint8 (fallback); + + sl << uint32 (facesets[fallback].faces[face_num].checksum) + << new_faces[face_num].name; + + ns->send_packet (sl); } else { + sl << (ns->image2 ? "image2 " : "image ") + << uint32 (face_num); + if (ns->image2) - strcpy ((char *) sl.buf, "image2 "); - else - strcpy ((char *) sl.buf, "image "); - sl.len = strlen ((char *) sl.buf); - SockList_AddInt (&sl, face_num); - if (ns->image2) - SockList_AddChar (&sl, fallback); - SockList_AddInt (&sl, facesets[fallback].faces[face_num].datalen); - memcpy (sl.buf + sl.len, facesets[fallback].faces[face_num].data, facesets[fallback].faces[face_num].datalen); - sl.len += facesets[fallback].faces[face_num].datalen; - Send_With_Handling (ns, &sl); + sl << uint8 (fallback); + + sl << uint32 (facesets[fallback].faces[face_num].datalen) + << data (facesets[fallback].faces[face_num].data, facesets[fallback].faces[face_num].datalen); + + ns->send_packet (sl); } + ns->faces_sent[face_num] |= NS_FACESENT_FACE; - free (sl.buf); } /** @@ -435,26 +415,19 @@ */ void -send_image_info (NewSocket * ns, char *params) +send_image_info (client *ns, char *params) { - SockList sl; - int i; + packet sl; - sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + sl.printf ("replyinfo image_info\n%d\n%u\n", nrofpixmaps - 1, (unsigned int)bmaps_checksum); - sprintf ((char *) sl.buf, "replyinfo image_info\n%d\n%d\n", nrofpixmaps - 1, bmaps_checksum); - for (i = 0; i < MAX_FACE_SETS; i++) - { - if (facesets[i].prefix) - { - sprintf ((char *) sl.buf + strlen ((const char *) sl.buf), "%d:%s:%s:%d:%s:%s:%s", - i, facesets[i].prefix, facesets[i].fullname, facesets[i].fallback, - facesets[i].size, facesets[i].extension, facesets[i].comment); - } - } - sl.len = strlen ((const char *) sl.buf); - Send_With_Handling (ns, &sl); - free (sl.buf); + for (int i = 0; i < MAX_FACE_SETS; i++) + if (facesets[i].prefix) + sl.printf ("%d:%s:%s:%d:%s:%s:%s", i, + facesets[i].prefix, facesets[i].fullname , facesets[i].fallback, + facesets[i].size , facesets[i].extension, facesets[i].comment); + + ns->send_packet (sl); } /** @@ -467,15 +440,12 @@ * - name */ void -send_image_sums (NewSocket * ns, char *params) +send_image_sums (client *ns, char *params) { int start, stop; - short i; - char qq; - char *cp, buf[MAX_BUF]; - SockList sl; + char *cp; - sl.buf = (unsigned char *) malloc (MAXSOCKBUF); + packet sl; start = atoi (params); for (cp = params; *cp != '\0'; cp++) @@ -485,39 +455,37 @@ stop = atoi (cp); if (stop < start || *cp == '\0' || (stop - start) > 1000 || stop >= nrofpixmaps) { - sprintf (buf, "replyinfo image_sums %d %d", start, stop); - cs_write_string (ns, buf, strlen (buf)); + sl.printf ("replyinfo image_sums %d %d", start, stop); + ns->send_packet (sl); + sl.reset (); return; } - sprintf ((char *) sl.buf, "replyinfo image_sums %d %d ", start, stop); - sl.len = strlen ((const char *) sl.buf); + sl.printf ("replyinfo image_sums %d %d ", start, stop); - for (i = start; i <= stop; i++) + for (int i = start; i <= stop; i++) { - SockList_AddShort (&sl, i); ns->faces_sent[i] |= NS_FACESENT_FACE; - qq = get_face_fallback (ns->faceset, i); - SockList_AddInt (&sl, facesets[qq].faces[i].checksum); - SockList_AddChar (&sl, qq); - - qq = strlen (new_faces[i].name); - SockList_AddChar (&sl, (char) (qq + 1)); - strcpy ((char *) sl.buf + sl.len, new_faces[i].name); - sl.len += qq; - SockList_AddChar (&sl, 0); + int qq = get_face_fallback (ns->faceset, i); + + sl << uint16 (i) + << uint32 (facesets[qq].faces[i].checksum) + << uint8 (qq) + << data8 (&new_faces[i].name, new_faces[i].name.length () + 1); } + /* It would make more sense to catch this pre-emptively in the code above. * however, if this really happens, we probably just want to cut down the * size to less than 1000, since that is what we claim the protocol would * support. */ - if (sl.len >= MAXSOCKBUF) + if (sl.length () >= MAXSOCKBUF) { - LOG (llevError, "send_image_send: buffer overrun, %d > %d\n", sl.len, MAXSOCKBUF); + LOG (llevError, "send_image_send: buffer overrun, %d > %d\n", sl.length (), MAXSOCKBUF); abort (); } - Send_With_Handling (ns, &sl); - free (sl.buf); + + ns->send_packet (sl); } +