1 /*
2 
3     eboard - chess client
4     http://www.bergo.eng.br/eboard
5     https://github.com/fbergo/eboard
6     Copyright (C) 2000-2016 Felipe Bergo
7     fbergo/at/gmail/dot/com
8 
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13 
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18 
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 
23 */
24 
25 
26 
27 #ifndef EBOARD_NETWORK_H
28 #define EBOARD_NETWORK_H 1
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <errno.h>
36 
37 #include <sys/time.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <netdb.h>
41 #include <netinet/in.h>
42 
43 #include "config.h"
44 
45 #ifdef NEED_TCP_H
46 #include <netinet/tcp.h>
47 #endif
48 
49 #include <arpa/inet.h>
50 
51 #include <gtk/gtk.h>
52 
53 #include "stl.h"
54 #include "eboard.h"
55 
56 class PidIssuer {
57  public:
58   virtual void farewellPid(int dpid)=0;
59 };
60 
61 class Parent {
62  public:
63   Parent(PidIssuer *a,int b);
64   int operator==(int v);
65   PidIssuer *issuer;
66   int pid;
67 };
68 
69 class PidRing : public SigChildHandler {
70  public:
~PidRing()71   virtual ~PidRing() {}
72   void add(PidIssuer *po, int pid);
73   void remove(PidIssuer *po);
74   void funeral(int pid);
75   virtual void ZombieNotification(int pid);
76  private:
77   list<Parent *> parents;
78 };
79 
80 class NetConnection {
81  public:
82   NetConnection();
83   virtual ~NetConnection();
84 
85   virtual int isConnected();
86 
87   // 0 ok, -1 error, msg in getError
88   virtual int  open()=0;
89 
90   virtual void close()=0;
91 
92   // -1 if nothing available, 0 when line ok
93   virtual int readLine(char *tbuffer,int limit)=0;
94 
95   virtual void writeLine(const char *tbuffer)=0;
96 
97   virtual int  readPartial(char *tbuffer,int limit)=0;
98   virtual bool bufferMatch(const char *match)=0;
99 
100   virtual char *getError()=0;
101 
102   virtual int  hasTimeGuard();
103 
104   virtual int  getReadHandle()=0;
105 
106   char HostName[128];
107   char HostAddress[96];
108 
109   int  TimeGuard;
110 
111   virtual void notifyReadReady(IONotificationInterface *target);
112   virtual void sendReadNotify();
113 
114   void cleanUp();
115 
116  private:
117   int  TagRead;
118   IONotificationInterface *listener;
119 
120   friend void netconn_read_notify(gpointer data, gint source,
121 				  GdkInputCondition cond);
122 };
123 
124 void netconn_read_notify(gpointer data, gint source,
125 			 GdkInputCondition cond);
126 
127 class RingBuffer {
128  public:
129   RingBuffer(int _size);
130   ~RingBuffer();
131 
132   bool empty() const;
133   bool full() const;
134 
135   char pop();
136   bool push(char c);
137   char last() const;
138 
139   string getLine();
140 
141   string toString(int maxlen=-1) const;
142 
143   void status();
144 
145  private:
146   char *data;
147   int rp,wp,len,size;
148 };
149 
150 class BufferedConnection : public NetConnection {
151  public:
BufferedConnection()152  BufferedConnection() : buffer(64<<10) { }
153 
154   virtual int  readPartial(char *tbuffer,int limit);
155   virtual bool bufferMatch(const char *match);
156  protected:
157   virtual int innerReadLine(char *tbuffer,int limit,int handle);
158   int  consume(int handle, int amount=128);
159   int  produce(char *tbuffer,int limit,int handle);
160   RingBuffer buffer;
161 };
162 
163 class DirectConnection : public BufferedConnection {
164  public:
165   DirectConnection(const char *hostname,int port);
166 
167   int open();
168   void close();
169   int readLine(char *tbuffer,int limit);
170   void writeLine(const char *obuffer);
171   int isConnected();
172 
173   char *getError();
174   int  getReadHandle();
175 
176  private:
177   int Port;
178   int Connected;
179   char errorMessage[128];
180 
181   struct hostent *he;
182   struct sockaddr_in sa;
183   int netsocket;
184 };
185 
186 class IncomingConnection : public BufferedConnection {
187  public:
188   IncomingConnection(int port);
189 
190   int open();
191   void close();
192   int readLine(char *tbuffer, int limit);
193   void writeLine(const char *obuffer);
194   int isConnected();
195 
196   char *getError();
197   int  getReadHandle();
198 
199  private:
200   int Port;
201   int Connected;
202   char errorMessage[128];
203   int netsocket;
204 
205   int createSocket();
206   int acceptConnection();
207 };
208 
209 class PipeConnection : public BufferedConnection,
210                        public PidIssuer
211 {
212  public:
213   PipeConnection(int _pin,int _pout);
214   /// chess engine constructor
215   PipeConnection(const char *helperbin,const char *arg1=NULL,const char *arg2=NULL,const char *arg3=NULL,const char *arg4=NULL);
216   /// timeseal constructor
217   PipeConnection(const char *host,int port, const char *helperbin,const char *helpersuffix);
218   virtual ~PipeConnection();
219 
220   int Quiet;
221 
222   int isConnected();
223 
224   // 0 ok, -1 error, msg in getError
225   int  open();
226 
227   void close();
228 
229   void setHandshake(const char *s);
230 
231   // -1 if nothing available, 0 when line ok
232   int readLine(char *tbuffer,int limit);
233   void writeLine(const char *obuffer);
234   char *getError();
235   int   getReadHandle();
236 
237   virtual void farewellPid(int dpid);
238   void setMaxWaitTime(double msecs);
239 
240  private:
241   void init();
242   void checkChildren();
243   friend gboolean sched_close(gpointer data);
244   friend gboolean pipewatch_handler(gpointer data);
245 
246   int  opmode; // 0=engine with bare args, 1=timeseal with network host
247   int  pout, pin;
248   int  Connected;
249   int  Port;
250   char HelperBin[512];
251   char errorMessage[128];
252   vector<const char *> args;
253   int  pid;
254   int  toid; // timeout
255   string handshake;
256   int  use_execve;
257   double MaxWaitTime; // msecs
258 
259 };
260 
261 gboolean sched_close(gpointer data);
262 
263 class FallBackConnection : public NetConnection {
264  public:
265   FallBackConnection();
266   ~FallBackConnection();
267   void append(NetConnection *nc);
268 
269   virtual int  isConnected();
270   virtual int  open();
271   virtual void close();
272   virtual int  readLine(char *tbuffer,int limit);
273   virtual void writeLine(const char *tbuffer);
274   virtual int  readPartial(char *tbuffer,int limit);
275   virtual bool bufferMatch(const char *match);
276   virtual char *getError();
277   virtual int getReadHandle();
278 
279   virtual void notifyReadReady(IONotificationInterface *target);
280   virtual void sendReadNotify();
281  private:
282   int Connected;
283   list<NetConnection *>::iterator current;
284   list<NetConnection *> candidates;
285   char errorMessage[128];
286 };
287 
288 void pipewatch_start();
289 void pipewatch_end();
290 
291 #endif
292