Crossfire Server  1.75.0
image.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
25 #include "global.h"
26 
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "image.h"
31 #include "newserver.h"
32 #include "shared/newclient.h"
33 #include "sproto.h"
34 #include "assets.h"
35 #include "AssetsManager.h"
36 
45 void send_face_cmd(char *buff, int len, socket_struct *ns) {
46  long tmpnum;
47  uint16_t faceid;
48 
49  if (len <= 0 || !buff) {
50  LOG(llevDebug, "IP '%s' sent bogus send_face_cmd information\n", ns->host);
51  return;
52  }
53 
54  tmpnum = atoi(buff);
55  faceid = tmpnum&0xffff;
56 
57  if (faceid != 0)
58  esrv_send_face(ns, get_face_by_id(faceid), 1);
59 }
60 
72 void esrv_send_face(socket_struct *ns, const Face *face, int nocache) {
73  SockList sl;
74 
75  if (face == NULL) {
76  LOG(llevError, "esrv_send_face NULL??\n");
77  return;
78  }
79 
80  SockList_Init(&sl);
82 
83  if (!fs || fs->faces[face->number].data == NULL) {
84  LOG(llevError, "esrv_send_face: faces[%d].data == NULL\n", face->number);
85  return;
86  }
87 
88  if (ns->facecache && !nocache) {
89  SockList_AddString(&sl, "face2 ");
90  SockList_AddShort(&sl, face->number);
91  SockList_AddChar(&sl, fs->id);
92  SockList_AddInt(&sl, fs->faces[face->number].checksum);
93  SockList_AddString(&sl, face->name);
94  Send_With_Handling(ns, &sl);
95  } else {
96  SockList_AddString(&sl, "image2 ");
97  SockList_AddInt(&sl, face->number);
98  SockList_AddChar(&sl, fs->id);
99  SockList_AddInt(&sl, fs->faces[face->number].datalen);
100  SockList_AddData(&sl, fs->faces[face->number].data, fs->faces[face->number].datalen);
101  Send_With_Handling(ns, &sl);
102  }
103  ns->faces_sent[face->number] |= NS_FACESENT_FACE;
104  SockList_Term(&sl);
105 }
106 
114  SockList sl;
115 
116  SockList_Init(&sl);
117 
118  SockList_AddPrintf(&sl, "replyinfo image_info\n%d\n%d\n", get_faces_count()-1, getManager()->faces()->checksum());
119  getManager()->facesets()->each([&sl] (const face_sets *fs) {
120  SockList_AddPrintf(&sl, "%d:%s:%s:%d:%s:%s:%s\n",
121  fs->id, fs->prefix, fs->fullname,
122  fs->fallback ? fs->fallback->id : 0, fs->size,
123  fs->extension, fs->comment);
124  });
125  Send_With_Handling(ns, &sl);
126  SockList_Term(&sl);
127 }
128 
138 void send_image_sums(socket_struct *ns, char *params) {
139  unsigned int start, stop;
140  unsigned short i;
141  char *cp;
142  SockList sl;
143 
144  // Sanity check:
145  // If no params, bail out with an error.
146  // Otherwise, a rogue client could produce a segfault by supplying "requestinfo image_sums" without parameters.
147  if (params == NULL) {
148  LOG(llevError, "send_image_sums: bogus \"requestinfo image_sums\": no range provided.\n");
149  return;
150  }
151 
152  SockList_Init(&sl);
153 
154  start = atoi(params);
155  for (cp = params; *cp != '\0'; cp++)
156  if (*cp == ' ')
157  break;
158 
159  stop = atoi(cp);
160  if (stop < start
161  || *cp == '\0'
162  || (stop-start) > 1000
163  || stop >= get_faces_count()) {
164  SockList_AddPrintf(&sl, "replyinfo image_sums %d %d", start, stop);
165  Send_With_Handling(ns, &sl);
166  SockList_Term(&sl);
167  return;
168  }
169  SockList_AddPrintf(&sl, "replyinfo image_sums %d %d ", start, stop);
170 
171  for (i = start; i <= stop; i++) {
172  const Face *face = get_face_by_id(i);
173 
174  if (SockList_Avail(&sl) < 2+4+1+1+strlen(face->name)+1) {
175  LOG(llevError, "send_image_sums: buffer overflow, rejecting range %d..%d\n", start, stop);
176  SockList_Reset(&sl);
177  SockList_AddPrintf(&sl, "replyinfo image_sums %d %d", start, stop);
178  Send_With_Handling(ns, &sl);
179  SockList_Term(&sl);
180  return;
181  }
182 
183  SockList_AddShort(&sl, i);
184  ns->faces_sent[face->number] |= NS_FACESENT_FACE;
185 
187  SockList_AddInt(&sl, fs->faces[i].checksum);
188  SockList_AddChar(&sl, fs->id);
189  SockList_AddLen8Data(&sl, face->name, strlen(face->name)+1);
190  }
191  Send_With_Handling(ns, &sl);
192  SockList_Term(&sl);
193 }
Error, serious thing.
Definition: logger.h:11
void SockList_AddPrintf(SockList *sl, const char *format,...)
Adds a printf like formatted string.
Definition: lowlevel.cpp:202
uint8_t faceset
Set the client is using, default 0.
Definition: newserver.h:121
void SockList_Reset(SockList *sl)
Resets the length of the stored data for writing.
Definition: lowlevel.cpp:74
#define NS_FACESENT_FACE
Bitmask for the faces_sent[] array - what portion of the face have we sent?
Definition: newserver.h:141
face_info * faces
images in this faceset
Definition: image.h:26
void send_image_info(socket_struct *ns)
Sends the number of images, checksum of the face file, and the image_info file information.
Definition: image.cpp:113
void SockList_Init(SockList *sl)
Initializes the SockList instance.
Definition: lowlevel.cpp:55
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
Defines various flags that both the new client and new server use.
New face structure - this enforces the notion that data is face by face only - you can not change the...
Definition: face.h:14
void SockList_AddShort(SockList *sl, uint16_t data)
Adds a 16 bit value.
Definition: lowlevel.cpp:116
Socket structure, represents a client-server connection.
Definition: newserver.h:93
int id
Definition: image.h:18
int get_face_fallback(int faceset, uint16_t imageno)
This returns the set we will actually use when sending a face.
Definition: image.cpp:133
face_sets * find_faceset(int id)
Definition: assets.cpp:332
void SockList_AddInt(SockList *sl, uint32_t data)
Adds a 32 bit value.
Definition: lowlevel.cpp:127
Facesets * facesets()
Get facesets.
Definition: AssetsManager.h:65
Global type definitions and header inclusions.
void esrv_send_face(socket_struct *ns, const Face *face, int nocache)
Sends a face to a client if they are in pixmap mode, nothing gets sent in bitmap mode.
Definition: image.cpp:72
static unsigned checksum(const mtar_raw_header_t *rh)
Definition: microtar.cpp:49
char * host
Which host it is connected from (ip address).
Definition: newserver.h:104
void send_image_sums(socket_struct *ns, char *params)
Sends requested face information.
Definition: image.cpp:138
AssetsManager * getManager()
Definition: assets.cpp:309
uint32_t facecache
If true, client is caching images.
Definition: newserver.h:106
void SockList_AddData(SockList *sl, const void *data, size_t len)
Adds a data block.
Definition: lowlevel.cpp:167
Image-related structures.
uint8_t * data
Image data.
Definition: image.h:11
void SockList_Term(SockList *sl)
Frees all resources allocated by a SockList instance.
Definition: lowlevel.cpp:65
char * prefix
Faceset short name, used in pictures names (base, clsc).
Definition: image.h:19
char * extension
Supplementary description.
Definition: image.h:23
void SockList_AddString(SockList *sl, const char *data)
Adds a string without length.
Definition: lowlevel.cpp:157
Defines various structures and values that are used for the new client server communication method...
size_t get_faces_count()
Definition: assets.cpp:297
char * size
Human-readable set size.
Definition: image.h:22
size_t SockList_Avail(const SockList *sl)
Returns the available bytes in a SockList instance.
Definition: lowlevel.cpp:246
uint16_t number
This is the image unique identifier.
Definition: face.h:15
uint32_t checksum
Checksum of face data.
Definition: image.h:13
char * comment
Human-readable comment for this set.
Definition: image.h:24
void SockList_AddChar(SockList *sl, unsigned char c)
Adds an 8 bit value.
Definition: lowlevel.cpp:106
uint16_t datalen
Length of data.
Definition: image.h:12
struct face_sets * fallback
Faceset to use when an image is not found in this faceset.
Definition: image.h:21
Only for debugging purposes.
Definition: logger.h:13
void SockList_AddLen8Data(SockList *sl, const void *data, size_t len)
Adds a data block prepended with an 8 bit length field.
Definition: lowlevel.cpp:179
void send_face_cmd(char *buff, int len, socket_struct *ns)
Client has requested pixmap that it somehow missed getting.
Definition: image.cpp:45
char * fullname
Full faceset name.
Definition: image.h:20
C function wrappers to interact with assets.
Contains the base information we use to make up a packet we want to send.
Definition: newclient.h:721
Information about one face set.
Definition: image.h:17
sstring name
Face name, as used by archetypes and such.
Definition: face.h:19
uint8_t * faces_sent
This is a bitmap on sent face status.
Definition: newserver.h:100
const Face * get_face_by_id(uint16_t id)
Get a face from its unique identifier.
Definition: assets.cpp:319
void Send_With_Handling(socket_struct *ns, SockList *sl)
Calls Write_To_Socket to send data to the client.
Definition: lowlevel.cpp:447
void each(std::function< void(T *)> op)
Apply a function to each asset.