Crossfire Client, Trunk  R20693
newsocket.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 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 
21 #include "client.h"
22 
23 #include <errno.h>
24 
25 #include "script.h"
26 
32 void SockList_Init(SockList *sl, guint8 *buf)
33 {
34  sl->len=0;
35  sl->buf=buf + 2; /* reserve two bytes for total length */
36 }
37 
43 void SockList_AddChar(SockList *sl, char c)
44 {
45  if (sl->len + 1 < MAX_BUF - 2){
46  sl->buf[sl->len++]=c;
47  }
48  else{
49  /*
50  * Cast c to an unsigned short so it displays correctly in the error message.
51  * Otherwise, it prints as a hexadecimal number in a funny box.
52  *
53  * SilverNexus 2014-06-12
54  */
55  LOG(LOG_ERROR,"SockList_AddChar","Could not write %hu to socket: Buffer full.\n", (unsigned short)c);
56  }
57 }
58 
64 void SockList_AddShort(SockList *sl, guint16 data)
65 {
66  if (sl->len + 2 < MAX_BUF - 2){
67  sl->buf[sl->len++] = (data>>8)&0xff;
68  sl->buf[sl->len++] = data & 0xff;
69  }
70  else{
71  LOG(LOG_ERROR,"SockList_AddShort","Could not write %hu to socket: Buffer full.\n", data);
72  }
73 }
74 
80 void SockList_AddInt(SockList *sl, guint32 data)
81 {
82  if (sl->len + 4 < MAX_BUF - 2){
83  sl->buf[sl->len++] = (data>>24)&0xff;
84  sl->buf[sl->len++] = (data>>16)&0xff;
85  sl->buf[sl->len++] = (data>>8)&0xff;
86  sl->buf[sl->len++] = data & 0xff;
87  }
88  else{
89  LOG(LOG_ERROR,"SockList_AddInt","Could not write %u to socket: Buffer full.\n", data);
90  }
91 }
92 
98 void SockList_AddString(SockList *sl, const char *str)
99 {
100  int len = strlen(str);
101 
102  if (sl->len + len > MAX_BUF-2) {
103  len = MAX_BUF-2 - sl->len;
104  }
105  memcpy(sl->buf + sl->len, str, len);
106  sl->len += len;
107 }
108 
112 int SockList_Send(SockList *sl, GSocketConnection* c) {
113  sl->buf[-2] = sl->len / 256;
114  sl->buf[-1] = sl->len % 256;
115  if (c == NULL) {
116  LOG(LOG_WARNING, "SockList_Send", "Sending data while not connected!");
117  return 1;
118  }
119  GOutputStream* out = g_io_stream_get_output_stream(G_IO_STREAM(c));
120  bool ret = g_output_stream_write_all(out, sl->buf - 2, sl->len + 2, NULL,
121  NULL, NULL);
122  return ret ? 0 : -1;
123 }
124 
130 char GetChar_String(const unsigned char *data)
131 {
132  return (data[0]);
133 }
134 
142 int GetInt_String(const unsigned char *data)
143 {
144  return ((data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]);
145 }
146 
154 gint64 GetInt64_String(const unsigned char *data)
155 {
156 #ifdef WIN32
157  return (((gint64)data[0]<<56) + ((gint64)data[1]<<48) +
158  ((gint64)data[2]<<40) + ((gint64)data[3]<<32) +
159  ((gint64)data[4]<<24) + ((gint64)data[5]<<16) + ((gint64)data[6]<<8) + (gint64)data[7]);
160 #else
161  return (((guint64)data[0]<<56) + ((guint64)data[1]<<48) +
162  ((guint64)data[2]<<40) + ((guint64)data[3]<<32) +
163  ((guint64)data[4]<<24) + (data[5]<<16) + (data[6]<<8) + data[7]);
164 #endif
165 }
166 
172 short GetShort_String(const unsigned char *data)
173 {
174  return ((data[0]<<8)+data[1]);
175 }
176 
190 static guint16 GetUShort_String(const unsigned char data[static 2]) // We want at least two characters.
191 {
192  return ((data[0]<<8)+data[1]);
193 }
194 
206 bool SockList_ReadPacket(GSocketConnection c[static 1], SockList sl[static 1],
207  size_t len, GError** error) {
208  GInputStream* in = g_io_stream_get_input_stream(G_IO_STREAM(csocket.fd));
209  gsize read;
210  if (!g_input_stream_read_all(in, sl->buf, 2, &read, NULL, error)) {
211  return false;
212  }
213  if (read != 2) {
214  sl->len = 0;
215  return true;
216  }
217  size_t to_read = (size_t)GetUShort_String(sl->buf);
218  if (to_read + 2 > len) {
219  g_set_error(error, CLIENT_ERROR, CLIENT_ERROR_TOOBIG,
220  "Server packet too big");
221  return false;
222  }
223  if (!g_input_stream_read_all(in, sl->buf + 2, to_read, &read, NULL, error)) {
224  return false;
225  }
226  if (read != to_read) {
227  sl->len = 0;
228  return true;
229  }
230  sl->len = to_read + 2;
231 #ifdef CS_LOGSTATS
232  cst_tot.ibytes += sl->len;
233  cst_lst.ibytes += sl->len;
234 #endif
235  return true;
236 }
237 
245 int cs_print_string(GSocketConnection* fd, const char *str, ...)
246 {
247  va_list args;
248  SockList sl;
249  guint8 buf[MAX_BUF];
250 
251  SockList_Init(&sl, buf);
252  va_start(args, str);
253  sl.len += vsprintf((char*)sl.buf + sl.len, str, args);
254  va_end(args);
255 
256  script_monitor_str((char*)sl.buf);
257 
258  return SockList_Send(&sl, fd);
259 }
size_t len
Definition: newclient.h:685
void SockList_AddShort(SockList *sl, guint16 data)
Definition: newsocket.c:64
GSocketConnection * fd
Definition: client.h:120
unsigned char buf[MAXSOCKBUF]
Definition: newclient.h:686
void script_monitor_str(const char *command)
Definition: script.c:935
bool SockList_ReadPacket(GSocketConnection c[static 1], SockList sl[static 1], size_t len, GError **error)
Definition: newsocket.c:206
short GetShort_String(const unsigned char *data)
Definition: newsocket.c:172
static guint16 GetUShort_String(const unsigned char data[static 2])
Definition: newsocket.c:190
Warning that something might not work.
Definition: client.h:443
char GetChar_String(const unsigned char *data)
Definition: newsocket.c:130
ClientSocket csocket
Definition: client.c:69
static GInputStream * in
Definition: client.c:70
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:109
CS_Stats cst_lst
void SockList_AddInt(SockList *sl, guint32 data)
Definition: newsocket.c:80
int ibytes
Definition: newclient.h:694
int SockList_Send(SockList *sl, GSocketConnection *c)
Definition: newsocket.c:112
void SockList_AddString(SockList *sl, const char *str)
Definition: newsocket.c:98
#define MAX_BUF
Definition: client.h:40
gint64 GetInt64_String(const unsigned char *data)
Definition: newsocket.c:154
Warning that something definitely didn&#39;t work.
Definition: client.h:444
void SockList_AddChar(SockList *sl, char c)
Definition: newsocket.c:43
#define CLIENT_ERROR
Definition: client.h:638
CS_Stats cst_tot
void SockList_Init(SockList *sl, guint8 *buf)
Definition: newsocket.c:32
int cs_print_string(GSocketConnection *fd, const char *str,...)
Definition: newsocket.c:245
int GetInt_String(const unsigned char *data)
Definition: newsocket.c:142