Upgrade to Bonanza 6.0
[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(MNJ_LAN) || defined(DFPN)
14 void CONV shutdown_all( void )
15 {
16 #  if defined(MNJ_LAN)
17   sckt_shutdown( sckt_mnj );
18   sckt_mnj = SCKT_NULL;
19 #  endif
20
21 #  if defined(CSA_LAN)
22   sckt_shutdown( sckt_csa );
23   sckt_csa = SCKT_NULL;
24 #  endif
25
26 #  if defined(DFPN)
27   sckt_shutdown( dfpn_sckt );
28   dfpn_sckt = SCKT_NULL;
29 #  endif
30 }
31 #endif
32
33
34 #if defined(CSA_LAN) || defined(MNJ_LAN) || defined(DFPN_CLIENT)||defined(DFPN)
35 const char *
36 str_WSAError( const char *str )
37 {
38 #  if defined(_WIN32)
39   snprintf( str_message, SIZE_MESSAGE, "%s:%d", str,  WSAGetLastError() );
40   str_message[SIZE_MESSAGE-1] = '\0';
41   return str_message;
42 #  else
43   return str;
44 #  endif
45 }
46 #endif
47
48
49 #if defined(CSA_LAN)
50 int CONV
51 client_next_game( tree_t * restrict ptree, const char *str_addr, int iport )
52 {
53   int iret;
54   int my_turn;
55   const char *str_name1, *str_name2;
56   char buf1[SIZE_PLAYERNAME], buf2[SIZE_PLAYERNAME];
57
58   for ( ;; ) {
59
60     str_buffer_cmdline[0] = '\0';
61     sckt_csa = sckt_connect( str_addr, iport );
62     if ( sckt_csa == SCKT_NULL ) { return -2; }
63       
64     str_name1 = str_name2 = NULL;
65     iret = sckt_out( sckt_csa, "LOGIN %s %s\n",
66                      client_str_id, client_str_pwd );
67     if ( iret < 0 ) { return iret; }
68
69     Out( "wait for next game-conditions...\n" );
70
71     my_turn = black;
72     for ( ;; ) {
73
74       iret = next_cmdline( 1 );
75       if ( iret < 0 ) { return iret; }
76       else if ( game_status & flag_quit ) { return 1; }
77       
78       if      ( ! strcmp( str_cmdline, "END Game_Summary" ) ) { break; }
79       else if ( ! strcmp( str_cmdline, "Your_Turn:-" ) ) { my_turn = white; }
80       else if ( ! memcmp( str_cmdline, "Name+:", 6 ) )
81         {
82           strncpy( buf1, str_cmdline+6, SIZE_PLAYERNAME-1 );
83           buf1[SIZE_PLAYERNAME-1] = '\0';
84           str_name1 = buf1;
85         }
86       else if ( ! memcmp( str_cmdline, "Name-:", 6 ) )
87         {
88           strncpy( buf2, str_cmdline+6, SIZE_PLAYERNAME-1 );
89           buf2[SIZE_PLAYERNAME-1] = '\0';
90           str_name2 = buf2;
91         }
92     }
93
94     iret = sckt_out( sckt_csa, "AGREE\n" );
95     if ( iret < 0 ) { return -2; }
96
97     iret = next_cmdline( 1 );
98     if ( iret < 0 ) { return iret; }
99     else if ( game_status & flag_quit ) { return 1; }
100
101     if ( ! memcmp( str_cmdline, "REJECT:", 7 ) )
102       {
103         ShutdownAll();
104         continue;
105       }
106     else if ( ! memcmp( str_cmdline, "START:", 6 ) )   { break; }
107
108     str_error = str_server_err;
109     return -2;
110   }
111
112   if ( ini_game( ptree, &min_posi_no_handicap, flag_history,
113                  str_name1, str_name2 ) < 0 )
114     {
115       return -1;
116     }
117
118   if ( get_elapsed( &time_turn_start ) < 0 ) { return -1; }
119
120   client_turn   = my_turn;
121   client_ngame += 1;
122
123   Out( "Game Conditions (%dth):\n", client_ngame );
124   Out( "  my turn:%c\n", ach_turn[my_turn] );
125
126   if ( my_turn == root_turn )
127     {
128       iret = com_turn_start( ptree, 0 );
129       if ( iret < 0 ) { return iret; }
130     }
131
132   return 1;
133 }
134 #endif
135
136
137 #if defined(CSA_LAN)||defined(MNJ_LAN)|| defined(DFPN_CLIENT)|| defined(DFPN)
138 sckt_t CONV
139 sckt_connect( const char *str_addr, int iport )
140 {
141   struct hostent *phe;
142   struct sockaddr_in sin;
143   sckt_t sd;
144   u_long ul_addr;
145   int count;
146
147 #if defined(_WIN32)
148   {
149     WSADATA wsaData;
150     if ( WSAStartup( MAKEWORD(1,1), &wsaData ) )
151       {
152         str_error = str_WSAError( "WSAStartup() failed." );
153         return SCKT_NULL;
154       }
155   }
156 #endif
157
158   ul_addr = inet_addr( str_addr );
159   if ( ul_addr == INADDR_NONE )
160     {
161       phe = gethostbyname( str_addr );
162       if ( ! phe )
163         {
164           str_error = str_WSAError( "gethostbyname() faild." );
165 #if defined(_WIN32)
166           WSACleanup();
167 #endif
168           return SCKT_NULL;
169         }
170       ul_addr = *( (u_long *)phe->h_addr_list[0] );
171     }
172
173   sd = socket( AF_INET, SOCK_STREAM, 0 );
174   if ( sd == SCKT_NULL )
175     {
176       str_error = str_WSAError( "socket() faild." );
177 #if defined(_WIN32)
178       WSACleanup();
179 #endif
180       return SCKT_NULL;
181     }
182
183   for ( count = 0;; count += 1 ) {
184     
185     sin.sin_family      = AF_INET;
186     sin.sin_addr.s_addr = ul_addr;
187     sin.sin_port        = htons( (u_short)iport );
188     if ( connect( sd, (struct sockaddr *)&sin, sizeof(sin) ) != SOCKET_ERROR )
189       {
190         break;
191       }
192     
193     if ( ! count ) { Out( "connect() failed.  try again " ); }
194     else           { Out( "." ); }
195 #  if defined(_WIN32)
196     Sleep( 10000 );
197 #  else
198     sleep( 10 );
199 #  endif
200   }
201   if ( count ) { Out( "\n" ); }
202
203   return sd;
204 }
205
206
207 int CONV
208 sckt_shutdown( sckt_t sd )
209 {
210   int iret;
211
212   if ( sd == SCKT_NULL ) { return 1; }
213   out_warning( "shut down connection" );
214
215 #  if defined(_WIN32)
216   if ( shutdown( sd, SD_SEND ) == SOCKET_ERROR )
217     {
218       str_error = str_WSAError( "shutdown() faild:" );
219       WSACleanup();
220       return -2;
221     }
222
223   for ( ;; ) {
224     iret = recv( sd, str_message, SIZE_MESSAGE, 0 );
225     if ( iret == SOCKET_ERROR )
226       {
227         str_error = str_WSAError( "recv() failed:" );
228         WSACleanup();
229         return -2;
230       }
231     else if ( ! iret ) { break; }
232   }
233   
234   if ( closesocket( sd ) == SOCKET_ERROR )
235     {
236       str_error = str_WSAError( "closesocket() failed:" );
237       WSACleanup();
238       return -2;
239     }
240
241   if ( WSACleanup() == SOCKET_ERROR )
242     {
243       str_error = str_WSAError( "WSACleanup() faild:" );
244       return -2;
245     }
246
247   return 1;
248
249 #  else
250
251   if ( shutdown( sd, SHUT_RD ) == -1 )
252     {
253       str_error = "shutdown() faild.";
254       return -2;
255     }
256
257   for ( ;; ) {
258     iret = (int)recv( sd, str_message, SIZE_MESSAGE, 0 );
259     if ( iret == -1 )
260       {
261         str_error = "recv() failed.";
262         return -2;
263       }
264     else if ( ! iret ) { break; }
265   }
266   
267   if ( close( sd ) == -1 )
268     {
269       str_error = "close() failed.";
270       return -2;
271     }
272
273   return 1;
274 #  endif
275 }
276
277
278 int CONV sckt_recv_all( sckt_t sd )
279 {
280   int iret;
281
282   for ( ;; )
283     {
284 #  if defined(_WIN32)
285       iret = recv( sd, str_message, SIZE_MESSAGE, 0 );
286       if ( iret == SOCKET_ERROR || ! iret ) { break; }
287 #  else
288       iret = (int)recv( sd, str_message, SIZE_MESSAGE, 0 );
289       if ( iret == -1 || ! iret ) { break; }
290 #  endif
291     }
292
293   return 1;
294 }
295
296
297 int CONV
298 sckt_check( sckt_t sd )
299 {
300   struct timeval tv;
301   fd_set readfds;
302   int iret;
303
304   tv.tv_sec = tv.tv_usec = 0;
305
306   FD_ZERO( &readfds );
307 #  if defined(_MSC_VER)
308 #    pragma warning(disable:4127)
309 #  endif
310   FD_SET( sd, &readfds );
311 #  if defined(_MSC_VER)
312 #    pragma warning(default:4127)
313 #  endif
314
315   iret = select( (int)sd+1, &readfds, NULL, NULL, &tv );
316   if ( iret == SOCKET_ERROR )
317     {
318       str_error = str_WSAError( "select() with a socket connected failed:" );
319       return -2;
320     }
321
322   return iret;
323 }
324
325
326 int CONV
327 sckt_in( sckt_t sd, char *str, int n )
328 {
329   struct timeval tv;
330   fd_set readfds;
331   int iret;
332
333   for ( ;; ) {
334     Out( "wait for a message ... " );
335
336     tv.tv_sec  = SEC_KEEP_ALIVE;
337     tv.tv_usec = 0;
338     FD_ZERO( &readfds );
339 #  if defined(_MSC_VER)
340 #    pragma warning(disable:4127)
341 #  endif
342     FD_SET( sd, &readfds );
343 #  if defined(_MSC_VER)
344 #    pragma warning(default:4127)
345 #  endif
346
347     iret = select( (int)sd+1, &readfds, NULL, NULL, &tv );
348     if ( iret == SOCKET_ERROR )
349       {
350         str_error = str_WSAError( "select() with a socket connected failed." );
351         return -1;
352       }
353     if ( iret )
354       {
355         Out( "done.\n" );
356         break;
357       }
358     Out( "time out.\n" );
359
360     if ( sckt_out( sd, "\n" ) == SOCKET_ERROR )
361       {
362         str_error = str_WSAError( "send() failed:" );
363         return -1;
364       }
365   }
366
367   iret = recv( sd, str, n-1, 0 );
368   if ( iret == SOCKET_ERROR )
369     {
370       str_error = str_WSAError( "recv() failed:" );
371       return -1;
372     }
373   *( str + iret ) = '\0';
374
375   if ( ! iret )
376     {
377       Out( "Connection closed.\n" );
378       return 0;
379     }
380
381   Out( "%s[END]\n", str );
382   
383   return iret;
384 }
385
386
387 int CONV
388 sckt_out( sckt_t sd, const char *fmt, ... )
389 {
390   int nch;
391   char buf[256];
392   va_list arg;
393
394   va_start( arg, fmt );
395   nch = vsnprintf( buf, 256, fmt, arg );
396   va_end( arg );
397   if ( nch >= 256 || nch < 0 )
398     {
399       str_error = "buffer overflow at sckt_out()";
400       return -1;
401     }
402
403   Out( "- now sending the message: %s", buf );
404
405   if ( send( sd, buf, nch, 0 ) == SOCKET_ERROR )
406     {
407       str_error = str_WSAError( "send() failed:" );
408       return -1;
409     }
410
411   return get_elapsed( &time_last_send );
412 }
413 #endif /* CSA_LAN || MNJ_LAN || DFPN_CLIENT || DFPN */
414
415
416 #if defined(DFPN_CLIENT)
417 int CONV
418 dfpn_client_out( const char *fmt, ... )
419 {
420   int nch, iret;
421   char buf[256];
422   va_list arg;
423
424   if ( dfpn_client_sckt == SCKT_NULL ) { return 1; }
425
426   va_start( arg, fmt );
427   nch = vsnprintf( buf, 256, fmt, arg );
428   va_end( arg );
429
430   if ( nch >= 256 || nch < 0 )
431     {
432       sckt_shutdown( dfpn_client_sckt );
433       dfpn_client_sckt = SCKT_NULL;
434       out_warning( "A connection to DFPN server is down." );
435       return -1;
436     }
437
438   Out( "- send to DFPN server: %s", buf );
439
440   iret = send( dfpn_client_sckt, buf, nch, 0 );
441   if ( iret == SOCKET_ERROR )
442     {
443       sckt_shutdown( dfpn_client_sckt );
444       dfpn_client_sckt = SCKT_NULL;
445       out_warning( "A connection to DFPN server is down." );
446       return -1;
447     }
448
449   return 1;
450 }
451 #endif /* DFPN_CLIENT */