--- deliantra/server/socket/image.C 2006/08/13 17:16:05 1.1 +++ deliantra/server/socket/image.C 2006/12/14 20:39:54 1.11 @@ -1,9 +1,4 @@ /* - * static char *rcsid_init_c = - * "$Id: image.C,v 1.1 2006/08/13 17:16:05 elmex Exp $"; - */ - -/* CrossFire, A Multiplayer game for X-windows Copyright (C) 2001 Mark Wedel @@ -23,7 +18,7 @@ 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 + The author can be reached via e-mail to */ /** \file @@ -47,21 +42,29 @@ #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 */ +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; - uint8 fallback; /**< faceset to use when an image is not found in this faceset */ - char *size; - char *extension; - char *comment; - FaceInfo *faces; /**< images in this faceset */ +typedef struct +{ + + char *prefix; /**< */ + char *fullname; + + uint8 fallback; /**< faceset to use when an image is not found in this faceset */ + char *size; + char *extension; + char *comment; + + FaceInfo *faces; /**< images in this faceset */ } FaceSets; static FaceSets facesets[MAX_FACE_SETS]; /**< All facesets */ @@ -70,30 +73,36 @@ * Checks specified faceset is valid * \param fsn faceset number */ -int is_valid_faceset(int fsn) +int +is_valid_faceset (int fsn) { - if (fsn >=0 && fsn < MAX_FACE_SETS && facesets[fsn].prefix) return TRUE; - return FALSE; + if (fsn >= 0 && fsn < MAX_FACE_SETS && facesets[fsn].prefix) + return TRUE; + return FALSE; } /** * Frees all faceset information */ -void free_socket_images(void) +void +free_socket_images (void) { - int num,q; + int num, q; - for(num=0;num=MAX_FACE_SETS) { - 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].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]); - } - } - close_and_delete(infile,compressed); - for (i=0; i=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++) ; - 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 - * is embedded in the image file, so just ignore it. - */ - facesets[fileno].faces[num].datalen = len; - facesets[fileno].faces[num].data = (uint8*) malloc(len); - if ((i=fread(facesets[fileno].faces[num].data, len, 1, infile))!=1) { - 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; - for (i=0; i= MAX_FACE_SETS) + { + 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].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]); + } + } + 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. + */ + + for (fileno = 0; fileno < MAX_FACE_SETS; fileno++) + { + /* 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); + LOG (llevDebug, "Loading image file %s\n", filename); + + if ((infile = open_and_uncompress (filename, 0, &compressed)) == NULL) + { + LOG (llevError, "Unable to open %s\n", filename); + abort (); + } + while (fgets (buf, HUGE_BUF - 1, infile) != NULL) + { + if (strncmp (buf, "IMAGE ", 6) != 0) + { + 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++); + 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 of the image that + * is embedded in the image file, so just ignore it. + */ + facesets[fileno].faces[num].datalen = len; + facesets[fileno].faces[num].data = (uint8 *) malloc (len); + if ((i = fread (facesets[fileno].faces[num].data, len, 1, infile)) != 1) + { + 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; + 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; + } + } + close_and_delete (infile, compressed); + } /* For fileno < MAX_FACE_SETS */ } /** @@ -278,24 +313,22 @@ * */ -void SetFaceMode(char *buf, int len, NewSocket *ns) +void +SetFaceMode (char *buf, int len, client_socket *ns) { - char tmp[256]; + int mask = (atoi (buf) & CF_FACE_CACHE), mode = (atoi (buf) & ~CF_FACE_CACHE); - int mask =(atoi(buf) & CF_FACE_CACHE), mode=(atoi(buf) & ~CF_FACE_CACHE); - - if (mode==CF_FACE_NONE) { - 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 - } - if (mask) { - ns->facecache=1; + if (mode == CF_FACE_NONE) + ns->facecache = 1; + else if (mode != CF_FACE_PNG) + { + packet sl; + sl.printf ("drawinfo %d %s", NDI_RED, "Warning - send unsupported face mode. Will use Png"); + ns->send_packet (sl); } + + if (mask) + ns->facecache = 1; } /** @@ -304,13 +337,14 @@ * caching images. */ -void SendFaceCmd(char *buff, int len, NewSocket *ns) +void +SendFaceCmd (char *buff, int len, client_socket * ns) { - long tmpnum = atoi(buff); - short facenum=tmpnum & 0xffff; + long tmpnum = atoi (buff); + short facenum = tmpnum & 0xffff; - if(facenum!=0) - esrv_send_face(ns, facenum,1); + if (facenum != 0) + esrv_send_face (ns, facenum, 1); } /** @@ -322,59 +356,54 @@ * we look at the facecache, and if set, send the image name. */ -void esrv_send_face(NewSocket *ns,short face_num, int nocache) +void +esrv_send_face (client_socket *ns, short face_num, int nocache) { - SockList sl; - char fallback; + char fallback; - if (face_num <= 0 || face_num >= nrofpixmaps) { - LOG(llevError,"esrv_send_face (%d) out of bounds??\n",face_num); - return; - } - - sl.buf = (unsigned char*) malloc(MAXSOCKBUF); - fallback = get_face_fallback(ns->faceset, face_num); - - if (facesets[fallback].faces[face_num].data == NULL) { - LOG(llevError,"esrv_send_face: faces[%d].data == NULL\n",face_num); - return; - } - - 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.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); - } - else { - 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); + if (face_num <= 0 || face_num >= nrofpixmaps) + { + LOG (llevError, "esrv_send_face (%d) out of bounds??\n", face_num); + return; } - ns->faces_sent[face_num] |= NS_FACESENT_FACE; - free(sl.buf); + + packet sl; + fallback = get_face_fallback (ns->faceset, face_num); + + if (facesets[fallback].faces[face_num].data == NULL) + { + LOG (llevError, "esrv_send_face: faces[%d].data == NULL\n", face_num); + return; + } + + if (ns->facecache && !nocache) + { + sl << (ns->image2 ? "face2 " : "face1 ") + << uint16 (face_num); + + if (ns->image2) + 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) + 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; } /** @@ -383,24 +412,20 @@ * if you want further detail. */ -void send_image_info(NewSocket *ns, char *params) +void +send_image_info (client_socket * ns, char *params) { - SockList sl; - int i; + packet sl; + + sl.printf ("replyinfo image_info\n%d\n%d\n", nrofpixmaps - 1, bmaps_checksum); - sl.buf = (unsigned char *) malloc(MAXSOCKBUF); + 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); - sprintf((char*)sl.buf,"replyinfo image_info\n%d\n%d\n", nrofpixmaps-1, bmaps_checksum); - for (i=0; isend_packet (sl); } /** @@ -412,53 +437,53 @@ * - checksum * - name */ -void send_image_sums(NewSocket *ns, char *params) +void +send_image_sums (client_socket * ns, char *params) { - int start, stop; - short i; - char qq; - char *cp, buf[MAX_BUF]; - SockList sl; - - sl.buf = (unsigned char *) malloc(MAXSOCKBUF); - - start = atoi(params); - for (cp = params; *cp != '\0'; cp++) - if (*cp == ' ') break; - - 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)); - return; - } - sprintf((char*)sl.buf,"replyinfo image_sums %d %d ", start, stop); - - sl.len = strlen((const char*)sl.buf); - - for (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); - } - /* 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) { - LOG(llevError,"send_image_send: buffer overrun, %d > %d\n", sl.len, MAXSOCKBUF); - abort(); + int start, stop; + char *cp, buf[MAX_BUF]; + + packet sl; + + start = atoi (params); + for (cp = params; *cp != '\0'; cp++) + if (*cp == ' ') + break; + + stop = atoi (cp); + if (stop < start || *cp == '\0' || (stop - start) > 1000 || stop >= nrofpixmaps) + { + sl.printf ("replyinfo image_sums %d %d", start, stop); + ns->send_packet (sl); + sl.reset (); + return; + } + + sl.printf ("replyinfo image_sums %d %d ", start, stop); + + for (int i = start; i <= stop; i++) + { + ns->faces_sent[i] |= NS_FACESENT_FACE; + + 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.length () >= 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); } +