1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
/*
* Crossfire -- cooperative multi-player graphical RPG and adventure game
*
* Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
* Copyright (c) 1992 Frank Tore Johansen
*
* Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
* welcome to redistribute it under certain conditions. For details, please
* see COPYING and LICENSE.
*
* The authors can be reached via e-mail at <crossfire@metalforge.org>.
*/
/** \file
* Image related communication
*
* \date 2006-03-18
*
* This file deals with the image related communication to the
* client. I've located all the functions in this file - this
* localizes it more, and means that we don't need to declare
* things like all the structures as globals.
*/
#include "global.h"
#include <stdlib.h>
#include <string.h>
#include "image.h"
#include "newserver.h"
#include "shared/newclient.h"
#include "sproto.h"
/**
* Client has requested pixmap that it somehow missed getting.
* This will be called often if the client is
* caching images.
* @param buff data received from the client.
* @param len length of buff, ignored.
* @param ns socket to send data to.
*/
void send_face_cmd(char *buff, int len, socket_struct *ns) {
long tmpnum;
uint16_t faceid;
if (len <= 0 || !buff) {
LOG(llevDebug, "IP '%s' sent bogus send_face_cmd information\n", ns->host);
return;
}
tmpnum = atoi(buff);
faceid = tmpnum&0xffff;
if (faceid != 0)
esrv_send_face(ns, get_face_by_id(faceid), 1);
}
/**
* Sends a face to a client if they are in pixmap mode,
* nothing gets sent in bitmap mode.
* If nocache is true (nonzero), ignore the cache setting from the client -
* this is needed for the askface, in which we really do want to send the
* 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.
* @param ns socket to send the date to.
* @param face face to send.
* @param nocache if 1 then send a 'image2', else depending on client cache setting.
*/
void esrv_send_face(socket_struct *ns, const Face *face, int nocache) {
SockList sl;
int fallback;
if (face == NULL) {
LOG(llevError, "esrv_send_face NULL??\n");
return;
}
SockList_Init(&sl);
fallback = get_face_fallback(ns->faceset, face->number);
if (facesets[fallback].faces[face->number].data == NULL) {
LOG(llevError, "esrv_send_face: faces[%d].data == NULL\n", face->number);
return;
}
if (ns->facecache && !nocache) {
SockList_AddString(&sl, "face2 ");
SockList_AddShort(&sl, face->number);
SockList_AddChar(&sl, fallback);
SockList_AddInt(&sl, facesets[fallback].faces[face->number].checksum);
SockList_AddString(&sl, face->name);
Send_With_Handling(ns, &sl);
} else {
SockList_AddString(&sl, "image2 ");
SockList_AddInt(&sl, face->number);
SockList_AddChar(&sl, fallback);
SockList_AddInt(&sl, facesets[fallback].faces[face->number].datalen);
SockList_AddData(&sl, facesets[fallback].faces[face->number].data, facesets[fallback].faces[face->number].datalen);
Send_With_Handling(ns, &sl);
}
ns->faces_sent[face->number] |= NS_FACESENT_FACE;
SockList_Term(&sl);
}
/**
* Sends the number of images, checksum of the face file,
* and the image_info file information. See the doc/Developers/protocol
* if you want further detail.
* @param ns socket to send data to.
*/
void send_image_info(socket_struct *ns) {
SockList sl;
int i;
SockList_Init(&sl);
SockList_AddPrintf(&sl, "replyinfo image_info\n%d\n%d\n", get_faces_count()-1, bmaps_checksum);
for (i = 0; i < MAX_FACE_SETS; i++) {
if (facesets[i].prefix) {
SockList_AddPrintf(&sl, "%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);
}
}
Send_With_Handling(ns, &sl);
SockList_Term(&sl);
}
/**
* Sends requested face information.
* \param ns socket to send to
* \param params contains first and last index of face
*
* For each image in [start..stop] sends
* - checksum
* - name
*/
void send_image_sums(socket_struct *ns, char *params) {
unsigned int start, stop;
unsigned short i;
char *cp;
SockList sl;
SockList_Init(&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 >= get_faces_count()) {
SockList_AddPrintf(&sl, "replyinfo image_sums %d %d", start, stop);
Send_With_Handling(ns, &sl);
SockList_Term(&sl);
return;
}
SockList_AddPrintf(&sl, "replyinfo image_sums %d %d ", start, stop);
for (i = start; i <= stop; i++) {
int faceset;
const Face *face = get_face_by_index(i);
if (SockList_Avail(&sl) < 2+4+1+1+strlen(face->name)+1) {
LOG(llevError, "send_image_sums: buffer overflow, rejecting range %d..%d\n", start, stop);
SockList_Reset(&sl);
SockList_AddPrintf(&sl, "replyinfo image_sums %d %d", start, stop);
Send_With_Handling(ns, &sl);
SockList_Term(&sl);
return;
}
SockList_AddShort(&sl, i);
ns->faces_sent[face->number] |= NS_FACESENT_FACE;
faceset = get_face_fallback(ns->faceset, i);
SockList_AddInt(&sl, facesets[faceset].faces[i].checksum);
SockList_AddChar(&sl, faceset);
SockList_AddLen8Data(&sl, face->name, strlen(face->name)+1);
}
Send_With_Handling(ns, &sl);
SockList_Term(&sl);
}
|