Crossfire Client, Trunk  R20996
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  if (debug_protocol) {
120  LOG(LOG_INFO, "C->S", "%s", sl->buf);
121  }
122  GOutputStream* out = g_io_stream_get_output_stream(G_IO_STREAM(c));
123  bool ret = g_output_stream_write_all(out, sl->buf - 2, sl->len + 2, NULL,
124  NULL, NULL);
125  return ret ? 0 : -1;
126 }
127 
133 char GetChar_String(const unsigned char *data)
134 {
135  return (data[0]);
136 }
137 
145 int GetInt_String(const unsigned char *data)
146 {
147  return ((data[0]<<24) + (data[1]<<16) + (data[2]<<8) + data[3]);
148 }
149 
157 gint64 GetInt64_String(const unsigned char *data)
158 {
159 #ifdef WIN32
160  return (((gint64)data[0]<<56) + ((gint64)data[1]<<48) +
161  ((gint64)data[2]<<40) + ((gint64)data[3]<<32) +
162  ((gint64)data[4]<<24) + ((gint64)data[5]<<16) + ((gint64)data[6]<<8) + (gint64)data[7]);
163 #else
164  return (((guint64)data[0]<<56) + ((guint64)data[1]<<48) +
165  ((guint64)data[2]<<40) + ((guint64)data[3]<<32) +
166  ((guint64)data[4]<<24) + (data[5]<<16) + (data[6]<<8) + data[7]);
167 #endif
168 }
169 
175 short GetShort_String(const unsigned char *data)
176 {
177  return ((data[0]<<8)+data[1]);
178 }
179 
193 static guint16 GetUShort_String(const unsigned char data[static 2]) // We want at least two characters.
194 {
195  return ((data[0]<<8)+data[1]);
196 }
197 
209 bool SockList_ReadPacket(GSocketConnection c[static 1], SockList sl[static 1],
210  size_t len, GError** error) {
211  GInputStream* in = g_io_stream_get_input_stream(G_IO_STREAM(csocket.fd));
212  gsize read;
213  if (!g_input_stream_read_all(in, sl->buf, 2, &read, NULL, error)) {
214  return false;
215  }
216  if (read != 2) {
217  sl->len = 0;
218  return true;
219  }
220  size_t to_read = (size_t)GetUShort_String(sl->buf);
221  if (to_read + 2 > len) {
222  g_set_error(error, CLIENT_ERROR, CLIENT_ERROR_TOOBIG,
223  "Server packet too big");
224  return false;
225  }
226  if (!g_input_stream_read_all(in, sl->buf + 2, to_read, &read, NULL, error)) {
227  return false;
228  }
229  if (read != to_read) {
230  sl->len = 0;
231  return true;
232  }
233  sl->len = to_read + 2;
234 #ifdef CS_LOGSTATS
235  cst_tot.ibytes += sl->len;
236  cst_lst.ibytes += sl->len;
237 #endif
238  return true;
239 }
240 
248 int cs_print_string(GSocketConnection* fd, const char *str, ...)
249 {
250  va_list args;
251  SockList sl;
252  guint8 buf[MAX_BUF];
253 
254  SockList_Init(&sl, buf);
255  va_start(args, str);
256  sl.len += vsprintf((char*)sl.buf + sl.len, str, args);
257  va_end(args);
258 
259  script_monitor_str((char*)sl.buf);
260 
261  return SockList_Send(&sl, fd);
262 }
size_t len
Definition: newclient.h:685
void SockList_AddShort(SockList *sl, guint16 data)
Definition: newsocket.c:64
GSocketConnection * fd
Definition: client.h:120
bool debug_protocol
Definition: main.c:61
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:209
short GetShort_String(const unsigned char *data)
Definition: newsocket.c:175
static guint16 GetUShort_String(const unsigned char data[static 2])
Definition: newsocket.c:193
Warning that something might not work.
Definition: client.h:443
char GetChar_String(const unsigned char *data)
Definition: newsocket.c:133
ClientSocket csocket
Definition: client.c:67
static GInputStream * in
Definition: client.c:68
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:111
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:157
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:637
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:248
int GetInt_String(const unsigned char *data)
Definition: newsocket.c:145
Minor, non-harmful issues.
Definition: client.h:442