Implement undo command
[bonanza.git] / sckt.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdarg.h>
4 #if ! defined(_WIN32)
5 #  include <arpa/inet.h>
6 #  include <sys/types.h>
7 #  include <sys/socket.h>
8 #  include <netdb.h>
9 #  include <unistd.h>
10 #endif
11 #include "shogi.h"
12
13 #if defined(CSA_LAN) || defined(DEKUNOBOU) || defined(MNJ_LAN)
14 const char *
15 str_WSAError( const char *str )
16 {
17 #  if defined(_WIN32)
18   snprintf( str_message, SIZE_MESSAGE, "%s:%d", str,  WSAGetLastError() );
19   str_message[SIZE_MESSAGE-1] = '\0';
20   return str_message;
21 #  else
22   return str;
23 #  endif
24 }
25 #endif
26
27
28 #if defined(CSA_LAN)
29 int
30 client_next_game( tree_t * restrict ptree, const char *str_addr, int iport )
31 {
32   int iret;
33   int my_turn;
34   const char *str_name1, *str_name2;
35   char buf1[SIZE_PLAYERNAME], buf2[SIZE_PLAYERNAME];
36
37   for ( ;; ) {
38
39     str_buffer_cmdline[0] = '\0';
40     sckt_csa = sckt_connect( str_addr, iport );
41     if ( sckt_csa == SCKT_NULL ) { return -2; }
42
43     str_name1 = str_name2 = NULL;
44     iret = sckt_out( sckt_csa, "LOGIN %s %s\n",
45                      client_str_id, client_str_pwd );
46     if ( iret < 0 ) { return iret; }
47
48     Out( "wait for next game-conditions...\n" );
49
50     my_turn = black;
51     for ( ;; ) {
52
53       iret = next_cmdline( 1 );
54       if ( iret < 0 ) { return iret; }
55       else if ( game_status & flag_quit ) { return 1; }
56       
57       if      ( ! strcmp( str_cmdline, "END Game_Summary" ) ) { break; }
58       else if ( ! strcmp( str_cmdline, "Your_Turn:-" ) ) { my_turn = white; }
59       else if ( ! memcmp( str_cmdline, "Name+:", 6 ) )
60         {
61           strncpy( buf1, str_cmdline+6, SIZE_PLAYERNAME-1 );
62           buf1[SIZE_PLAYERNAME-1] = '\0';
63           str_name1 = buf1;
64         }
65       else if ( ! memcmp( str_cmdline, "Name-:", 6 ) )
66         {
67           strncpy( buf2, str_cmdline+6, SIZE_PLAYERNAME-1 );
68           buf2[SIZE_PLAYERNAME-1] = '\0';
69           str_name2 = buf2;
70         }
71     }
72
73     iret = sckt_out( sckt_csa, "AGREE\n" );
74     if ( iret < 0 ) { return -2; }
75
76     iret = next_cmdline( 1 );
77     if ( iret < 0 ) { return iret; }
78     else if ( game_status & flag_quit ) { return 1; }
79
80     if ( ! memcmp( str_cmdline, "REJECT:", 7 ) )
81       {
82         ShutdownClient;
83         continue;
84       }
85     else if ( ! memcmp( str_cmdline, "START:", 6 ) )   { break; }
86
87     str_error = str_server_err;
88     return -2;
89   }
90
91   if ( ini_game( ptree, &min_posi_no_handicap, flag_history,
92                  str_name1, str_name2 ) < 0 )
93     {
94       return -1;
95     }
96
97   if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
98
99   client_turn   = my_turn;
100   client_ngame += 1;
101
102   Out( "Game Conditions (%dth):\n", client_ngame );
103   Out( "  my turn:%c\n", ach_turn[my_turn] );
104
105   if ( my_turn == root_turn )
106     {
107       iret = com_turn_start( ptree, 0 );
108       if ( iret < 0 ) { return iret; }
109     }
110
111   return 1;
112 }
113 #endif
114
115
116 #if defined(CSA_LAN) || defined(MNJ_LAN)
117 sckt_t
118 sckt_connect( const char *str_addr, int iport )
119 {
120   struct hostent *phe;
121   struct sockaddr_in sin;
122   sckt_t sd;
123   u_long ul_addr;
124
125 #if defined(_WIN32)
126   {
127     WSADATA wsaData;
128     if ( WSAStartup( MAKEWORD(1,1), &wsaData ) )
129       {
130         str_error = str_WSAError( "WSAStartup() failed." );
131         return SCKT_NULL;
132       }
133   }
134 #endif
135
136   ul_addr = inet_addr( str_addr );
137   if ( ul_addr == INADDR_NONE )
138     {
139       phe = gethostbyname( str_addr );
140       if ( ! phe )
141         {
142           str_error = str_WSAError( "gethostbyname() faild." );
143 #if defined(_WIN32)
144           WSACleanup();
145 #endif
146           return SCKT_NULL;
147         }
148       ul_addr = *( (u_long *)phe->h_addr_list[0] );
149     }
150
151   sd = socket( AF_INET, SOCK_STREAM, 0 );
152   if ( sd == SCKT_NULL )
153     {
154       str_error = str_WSAError( "socket() faild." );
155 #if defined(_WIN32)
156       WSACleanup();
157 #endif
158       return SCKT_NULL;
159     }
160
161   sin.sin_family      = AF_INET;
162   sin.sin_addr.s_addr = ul_addr;
163   sin.sin_port        = htons( (u_short)iport );
164   if ( connect( sd, (struct sockaddr *)&sin, sizeof(sin) ) == SOCKET_ERROR )
165     {
166       str_error = str_WSAError( "connect() faild." );
167 #if defined(_WIN32)
168       WSACleanup();
169 #endif
170       return SCKT_NULL;
171     }
172
173   return sd;
174 }
175
176
177 int
178 sckt_shutdown( sckt_t sd )
179 {
180   int iret;
181
182   if ( sd == SCKT_NULL ) { return 1; }
183   Out( "shut down connection\n" );
184
185 #  if defined(_WIN32)
186   if ( shutdown( sd, SD_SEND ) == SOCKET_ERROR )
187     {
188       str_error = str_WSAError( "shutdown() faild." );
189       WSACleanup();
190       return -2;
191     }
192
193   for ( ;; ) {
194     iret = recv( sd, str_message, SIZE_MESSAGE, 0 );
195     if ( iret == SOCKET_ERROR )
196       {
197         str_error = str_WSAError( "recv() failed." );
198         WSACleanup();
199         return -2;
200       }
201     else if ( ! iret ) { break; }
202   }
203   
204   if ( closesocket( sd ) == SOCKET_ERROR )
205     {
206       str_error = str_WSAError( "closesocket() failed." );
207       WSACleanup();
208       return -2;
209     }
210
211   if ( WSACleanup() == SOCKET_ERROR )
212     {
213       str_error = str_WSAError( "WSACleanup() faild." );
214       return -2;
215     }
216
217   return 1;
218
219 #  else
220   if ( shutdown( sd, SHUT_RD ) == -1 )
221     {
222       str_error = "shutdown() faild.";
223       return -2;
224     }
225
226   for ( ;; ) {
227     iret = (int)recv( sd, str_message, SIZE_MESSAGE, 0 );
228     if ( iret == -1 )
229       {
230         str_error = "recv() failed.";
231         return -2;
232       }
233     else if ( ! iret ) { break; }
234   }
235   
236   if ( close( sd ) == -1 )
237     {
238       str_error = "close() failed.";
239       return -2;
240     }
241
242   return 1;
243 #  endif
244 }
245
246
247 int
248 sckt_check( sckt_t sd )
249 {
250   struct timeval tv;
251   fd_set readfds;
252   int iret;
253
254   tv.tv_sec = tv.tv_usec = 0;
255
256   FD_ZERO( &readfds );
257 #  if defined(_MSC_VER)
258 #    pragma warning(disable:4127)
259 #  endif
260   FD_SET( sd, &readfds );
261 #  if defined(_MSC_VER)
262 #    pragma warning(default:4127)
263 #  endif
264
265   iret = select( (int)sd+1, &readfds, NULL, NULL, &tv );
266   if ( iret == SOCKET_ERROR )
267     {
268       str_error = str_WSAError( "select() with a socket connected failed." );
269       return -2;
270     }
271
272   return iret;
273 }
274
275
276 int
277 sckt_in( sckt_t sd, char *str, int n )
278 {
279   struct timeval tv;
280   fd_set readfds;
281   int iret;
282
283   for ( ;; ) {
284     Out( "wait for a message ... " );
285
286     tv.tv_sec  = SEC_KEEP_ALIVE;
287     tv.tv_usec = 0;
288     FD_ZERO( &readfds );
289 #  if defined(_MSC_VER)
290 #    pragma warning(disable:4127)
291 #  endif
292     FD_SET( sd, &readfds );
293 #  if defined(_MSC_VER)
294 #    pragma warning(default:4127)
295 #  endif
296
297     iret = select( (int)sd+1, &readfds, NULL, NULL, &tv );
298     if ( iret == SOCKET_ERROR )
299       {
300         str_error = str_WSAError( "select() with a socket connected failed." );
301         return -1;
302       }
303     if ( iret )
304       {
305         Out( "done.\n" );
306         break;
307       }
308     Out( "time out.\n" );
309
310     if ( sckt_out( sd, "\n" ) == SOCKET_ERROR )
311       {
312         str_error = str_WSAError( "send() failed." );
313         return -1;
314       }
315   }
316
317   iret = recv( sd, str, n-1, 0 );
318   if ( iret == SOCKET_ERROR )
319     {
320       str_error = str_WSAError( "recv() failed." );
321       return -1;
322     }
323   *( str + iret ) = '\0';
324
325   if ( ! iret )
326     {
327       Out( "Connection closed.\n" );
328       return 0;
329     }
330
331   Out( "%s[END]\n", str );
332   
333   return iret;
334 }
335
336
337 int
338 sckt_out( sckt_t sd, const char *fmt, ... )
339 {
340   int nch;
341   char buf[256];
342   va_list arg;
343
344   va_start( arg, fmt );
345   nch = vsnprintf( buf, 256, fmt, arg );
346   va_end( arg );
347   if ( nch >= 256 || nch < 0 )
348     {
349       str_error = "buffer overflow at sckt_out()";
350       return -1;
351     }
352
353   Out( "- now sending the message: %s", buf );
354
355   if ( send( sd, buf, nch, 0 ) == SOCKET_ERROR )
356     {
357       str_error = str_WSAError( "send() failed." );
358       return -1;
359     }
360
361   return get_elapsed( &time_last_send );
362 }
363 #endif /* CSA_LAN || MNJ_LAN */
364