1
/********************************************************************/
3
/* L I QQ U U I DD W W A RR 555 */
4
/* L I Q Q U U I D D W W A A R R 5 */
5
/* L I Q Q U U I D D W W W AAA RR 55 */
6
/* L I Q Q U U I D D WW WW A A R R 5 */
7
/* LLL I Q Q U I DD W W A A R R 55 */
17
/* U U TIRET FF O O O O T */
21
/********************************************************************/
23
/*****************************************************************************/
24
/* Liquid War is a unique multiplayer wargame */
25
/* Copyright (C) 1998-2002 Christian Mauduit */
27
/* This program is free software; you can redistribute it and/or modify */
28
/* it under the terms of the GNU General Public License as published by */
29
/* the Free Software Foundation; either version 2 of the License, or */
30
/* (at your option) any later version. */
32
/* This program is distributed in the hope that it will be useful, */
33
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
34
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
35
/* GNU General Public License for more details. */
37
/* You should have received a copy of the GNU General Public License */
38
/* along with this program; if not, write to the Free Software */
39
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
41
/* Liquid War homepage : http://www.ufoot.org/liquidwar */
42
/* Contact author : ufoot@ufoot.org */
43
/*****************************************************************************/
45
/********************************************************************/
46
/* name : sockw32.c */
47
/* content : simple wrappers on the winsock API */
48
/* last update : April 13th 2001 */
49
/********************************************************************/
51
/*==================================================================*/
53
/*==================================================================*/
58
#include <netinet/in.h>
59
#include <arpa/inet.h>
60
#include <sys/socket.h>
61
#include <sys/types.h>
77
/*==================================================================*/
79
/*==================================================================*/
81
#define LW_SOCK_RECV_SEC 8
82
#define LW_SOCK_RECV_USEC 0
83
#define LW_SOCK_SEND_SEC 8
84
#define LW_SOCK_SEND_USEC 0
86
#define LW_SOCK_SEND_BUFFER_SIZE 100
87
#define LW_SOCK_RECV_BUFFER_SIZE 200
89
/*==================================================================*/
91
/*==================================================================*/
94
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
97
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
100
/*==================================================================*/
102
/*==================================================================*/
104
/*==================================================================*/
105
/* static fonctions */
106
/*==================================================================*/
108
static void clean_buffer(char *buffer,int len);
110
/*==================================================================*/
112
/*==================================================================*/
114
/*------------------------------------------------------------------*/
116
* Cleans up a message buffer from all characters which are not
117
* plain standard ASCII. Used for logging information.
119
static void clean_buffer(char *buffer,int len)
125
if (!isalnum(buffer[i]) && buffer[i]!='-' && buffer[i]!='+')
132
/*------------------------------------------------------------------*/
134
* Returns true if the given number bytes is available on the socket
136
int lw_sock_peek_ex(int sock,int len)
142
char buffer[LW_SOCK_MESSAGE_SIZE];
144
if (len<=LW_SOCK_MESSAGE_SIZE-1)
150
res=select(sock+1,&read,NULL,NULL,&tv);
153
if (FD_ISSET(sock,&read))
156
* First we test if there's enough data available
158
if (recv(sock,buffer,len,MSG_PEEK)==len)
169
/*------------------------------------------------------------------*/
171
* Sends a string on the network.
172
* The advantage of this function over a raw "send" is that it does
173
* a "strlen" automatically to know the length of the string, and
174
* adds a tailing "\n" so that the message is "telnet compliant"
176
int lw_sock_send_str_ex(int sock, char *str)
180
char buffer[LW_SOCK_MESSAGE_SIZE];
188
* We put the string in a buffer, since we'll probably have
189
* to modify it (cut if it's too long, add a tailing '\n').
192
len=MIN(len,LW_SOCK_MESSAGE_SIZE-2);
193
strncpy(buffer,str,len);
199
while (total_sent<len && result)
203
tv.tv_sec=LW_SOCK_SEND_SEC;
204
tv.tv_usec=LW_SOCK_SEND_USEC;
207
res=select(sock+1,NULL,&write,NULL,&tv);
218
if (FD_ISSET(sock,&write))
220
sent=send(sock,buffer+total_sent,len-total_sent,0);
221
if (sent>0 && sent<=len-total_sent)
241
log_print_str(" > \"");
250
log_print_str(" > timeout!");
258
/*------------------------------------------------------------------*/
260
* Receives some data from the network.
261
* A tailing "\n" is expected. The routine handles both chr(10) and chr(13)
262
* correctly so that the program can be used with telnet under UNIX or
263
* windows without much trouble.
264
* This tailing "\n" is removed, so the return string is just the exact
265
* message which has been send with sock_send.
266
* Buffer must be able to accept at least LW_SOCK_MESSAGE_SIZE chars.
267
* Note that the function will not block forever, if there's no incoming
268
* for more than a #define specified amount of time, it will return
271
int lw_sock_recv_str_ex(int sock, char *str)
282
* We keep on trying to get data until
283
* - we get a '\n' character
284
* - the size of incoming data exceeds LW_SOCK_MESSAGE_SIZE
285
* - there's a reception low level error
290
while (!cr_found && pos<LW_SOCK_MESSAGE_SIZE-1 && result>0)
294
tv.tv_sec=LW_SOCK_RECV_SEC;
295
tv.tv_usec=LW_SOCK_RECV_USEC;
298
res=select(sock+1,&read,NULL,NULL,&tv);
310
* We check that the event we just received concerns the socket
311
* we are polling. If the event is not for us, let's consider
312
* everything is fine...
314
if (!FD_ISSET(sock,&read))
321
* We get the caracters one by one. This is a performance
322
* killer but we don't care since this routine is only
323
* used at the very beginning of the game, when the players
324
* are connecting themselves. And it has the *big* advantage
325
* that "netkeys" are not eaten up by this routine. More
326
* precisely, there's used to be a bug because when reading
327
* the final "OK" message, the clients read some netkeys
328
* along with it, which caused some network inconsistency
329
* since the messages had "disappeared".
331
if ((l=recv(sock,str+pos,1,0))<=0)
334
* OK, now we have received a message on this socket
335
* but there's no data. In most of the cases this means
336
* the socket is dead, so we return -1 instead of 0
337
* so that the caller can make the difference between
338
* a timeout (0) and a dead socket (-1).
345
* pos is an offset in the buffer. It is used to keep a
346
* trace of where new data should be appended in case we
347
* have to call recv several times to retrieve the whole
352
* We add a tailing '\0' so that the string is "C compliant"
356
* We seek for character 10, which should be '\n'
358
if ((cr=strchr(str,10))!=NULL)
362
* We handle the special character '13' for very often,
363
* especially when using telnet, the strings come
364
* with char(13)chr(10) at the end. So if it happens
365
* that after removing the 10 there's still a 13, then
366
* we remove the 13 as well.
368
if ((cr-str)>=1 && (*(cr-1))==13)
371
* Let's cut this ugly "ascii 13" character
372
* along with "ascii 10"
379
* No "ascii 13" in sight, simply remove "ascii 10"
398
log_print_str(" < \"");
407
log_print_str(" < timeout!");
415
/*------------------------------------------------------------------*/
417
* Sends a buffer on the network.
418
* Only a standard send wrapper
420
int lw_sock_send_buffer_ex(int sock, char *buffer,int len)
423
char trace[LW_SOCK_MESSAGE_SIZE];
430
if (len<=LW_SOCK_MESSAGE_SIZE-1)
433
while (total_sent<len && result)
437
tv.tv_sec=LW_SOCK_SEND_SEC;
438
tv.tv_usec=LW_SOCK_SEND_USEC;
441
res=select(sock+1,NULL,&write,NULL,&tv);
452
if (FD_ISSET(sock,&write))
457
LW_SOCK_SEND_BUFFER_SIZE),
459
if (sent>0 && sent<=len-total_sent)
478
strncpy(trace,buffer,len);
481
log_print_str(" > [");
482
clean_buffer(trace,len);
483
log_print_str(trace);
491
log_print_str(" > timeout!");
502
log_print_str(" > message too large!");
510
/*------------------------------------------------------------------*/
512
* Receives a buffer on the network.
513
* Only a standard recv wrapper
515
int lw_sock_recv_buffer_ex(int sock, char *buffer,int len)
518
char trace[LW_SOCK_MESSAGE_SIZE];
525
if (len<=LW_SOCK_MESSAGE_SIZE-1)
528
while (total_received<len && result)
532
tv.tv_sec=LW_SOCK_RECV_SEC;
533
tv.tv_usec=LW_SOCK_RECV_USEC;
536
res=select(sock+1,&read,NULL,NULL,&tv);
547
if (FD_ISSET(sock,&read))
550
buffer+total_received,
551
MIN(len-total_received,
552
LW_SOCK_RECV_BUFFER_SIZE),
554
if (received>0 && received<=len-total_received)
556
total_received+=received;
573
strncpy(trace,buffer,len);
576
log_print_str(" < [");
577
clean_buffer(trace,len);
578
log_print_str(trace);
586
log_print_str(" < timeout!");
597
log_print_str(" < message too large!");