1    	/****************************************************************************
2    	 *   Copyright (C) 2006-2008 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3    	 *   jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu              *
4    	 *                                                                          *
5    	 *   This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src).  *
6    	 *                                                                          *
7    	 *  DMTCP:dmtcp/src is free software: you can redistribute it and/or        *
8    	 *  modify it under the terms of the GNU Lesser General Public License as   *
9    	 *  published by the Free Software Foundation, either version 3 of the      *
10   	 *  License, or (at your option) any later version.                         *
11   	 *                                                                          *
12   	 *  DMTCP:dmtcp/src is distributed in the hope that it will be useful,      *
13   	 *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
14   	 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
15   	 *  GNU Lesser General Public License for more details.                     *
16   	 *                                                                          *
17   	 *  You should have received a copy of the GNU Lesser General Public        *
18   	 *  License along with DMTCP:dmtcp/src.  If not, see                        *
19   	 *  <http://www.gnu.org/licenses/>.                                         *
20   	 ****************************************************************************/
21   	
22   	#ifndef DMTCPCONNECTION_H
23   	#define DMTCPCONNECTION_H
24   	
25   	#include "dmtcpalloc.h"
26   	#include "dmtcpworker.h"
27   	#include "connectionidentifier.h"
28   	#include <vector>
29   	#include <sys/types.h>
30   	#include <sys/socket.h>
31   	#include <map>
32   	#include "../jalib/jbuffer.h"
33   	#include "../jalib/jserialize.h"
34   	#include "../jalib/jassert.h"
35   	#include "../jalib/jconvert.h"
36   	#include "../jalib/jalloc.h"
37   	#include "../jalib/jfilesystem.h"
38   	#include <sys/types.h>
39   	#include <sys/stat.h>
40   	#include <unistd.h>
41   	
42   	namespace jalib { class JSocket; }
43   	
44   	namespace dmtcp
45   	{
46   	
47   	  class KernelBufferDrainer;
48   	  class ConnectionRewirer;
49   	  class TcpConnection;
50   	  class KernelDeviceToConnection;
51   	  class ConnectionToFds;
52   	
53   	
54   	  class Connection
55   	  {
56   	    public:
57   	#ifdef JALIB_ALLOCATOR
58   	      static void* operator new(size_t nbytes, void* p) { return p; }
59   	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
60   	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
61   	#endif
62   	      enum ConnectionType
63   	      {
64   	        INVALID = 0x0000,
65   	        TCP     = 0x1000,
66   	        PIPE    = 0x2000,
67   	        PTY     = 0x3000,
68   	        FILE    = 0x4000,
69   	        STDIO   = 0x5000,
70   	        FIFO    = 0x6000,
71   	        TYPEMASK = TCP | PIPE | PTY | FILE | STDIO | FIFO
72   	      };
73   	
74   	      virtual ~Connection() {}
75   	
76   	      int conType() const { return _type & TYPEMASK; }
77   	      bool restoreInSecondIteration() { return _restoreInSecondIteration; }
78   	
79   	      const ConnectionIdentifier& id() const { return _id; }
80   	
81   	      virtual void preCheckpoint ( const dmtcp::vector<int>& fds, KernelBufferDrainer& ) = 0;
82   	      virtual void postCheckpoint ( const dmtcp::vector<int>& fds,
83   	                                    bool isRestart = false) = 0;
84   	      virtual void restore ( const dmtcp::vector<int>&, ConnectionRewirer& ) = 0;
85   	
86   	      virtual bool isDupConnection ( const Connection& _that, 
87   	                                     dmtcp::ConnectionToFds& conToFds ) { return false; };
88   	      virtual void doLocking ( const dmtcp::vector<int>& fds );
89   	      virtual void saveOptions ( const dmtcp::vector<int>& fds );
90   	      virtual void restoreOptions ( const dmtcp::vector<int>& fds );
91   	
92   	      virtual void doSendHandshakes( const dmtcp::vector<int>& fds, const dmtcp::UniquePid& coordinator ) {};
93   	      virtual void doRecvHandshakes( const dmtcp::vector<int>& fds, const dmtcp::UniquePid& coordinator ) {};
94   	
95   	      //called on restart when _id collides with another connection
96   	      virtual void mergeWith ( const Connection& that );
97   	
98   	      //convert with type checking
99   	      virtual TcpConnection& asTcp();
100  	
101  	      virtual void restartDup2(int oldFd, int newFd);
102  	
103  	
104  	      void serialize ( jalib::JBinarySerializer& o );
105  	    protected:
106  	      virtual void serializeSubClass ( jalib::JBinarySerializer& o ) = 0;
107  	    protected:
108  	      //only child classes can construct us...
109  	      Connection ( int t );
110  	    protected:
111  	      ConnectionIdentifier _id;
112  	      int                  _type;
113  	      int                  _fcntlFlags;
114  	      int                  _fcntlOwner;
115  	      int                  _fcntlSignal;
116  	      bool                 _restoreInSecondIteration;
117  	  };
118  	
119  	  class TcpConnection : public Connection
120  	  {
121  	    public:
122  	      enum TcpType
123  	      {
124  	        TCP_INVALID = TCP,
125  	        TCP_ERROR,
126  	        TCP_CREATED,
127  	        TCP_BIND,
128  	        TCP_LISTEN,
129  	        TCP_ACCEPT,
130  	        TCP_CONNECT,
131  	        TCP_PREEXISTING,
132  	        TCP_EXTERNAL_CONNECT
133  	      };
134  	
135  	      int tcpType() const { return _type; }
136  	
137  	#ifdef EXTERNAL_SOCKET_HANDLING
138  	      enum PeerType
139  	      {
140  	        PEER_UNKNOWN,
141  	        PEER_INTERNAL,
142  	        PEER_EXTERNAL
143  	      };
144  	
145  	      enum PeerType peerType() const { return _peerType; }
146  	
147  	      void markInternal() { 
148  	        if (_type == TCP_ACCEPT || _type == TCP_CONNECT) 
149  	          _peerType = PEER_INTERNAL; 
150  	      }
151  	      void markExternal() { 
152  	        if (_type == TCP_ACCEPT || _type == TCP_CONNECT) 
153  	          _peerType = PEER_EXTERNAL; 
154  	      }
155  	      void preCheckpointPeerLookup ( const dmtcp::vector<int>& fds,
156  	                                     dmtcp::vector<TcpConnectionInfo>& conInfoTable);
157  	#endif
158  	
159  	      //basic commands for updating state as a from wrappers
160  	      /*onSocket*/ TcpConnection ( int domain, int type, int protocol );
161  	      void onBind ( const struct sockaddr* addr, socklen_t len );
162  	      void onListen ( int backlog );
163  	      void onConnect( int sockfd = -1, const  struct sockaddr *serv_addr = NULL,
164  	                      socklen_t addrlen = 0 );
165  	      /*onAccept*/ TcpConnection ( const TcpConnection& parent, const ConnectionIdentifier& remote );
166  	      void onError();
167  	      void onDisconnect(const dmtcp::vector<int>& fds);
168  	      void addSetsockopt ( int level, int option, const char* value, int len );
169  	
170  	      void markPreExisting() { _type = TCP_PREEXISTING; }
171  	
172  	      //basic checkpointing commands
173  	      virtual void preCheckpoint ( const dmtcp::vector<int>& fds
174  	                                   , KernelBufferDrainer& drain );
175  	      virtual void postCheckpoint ( const dmtcp::vector<int>& fds,
176  	                                    bool isRestart = false);
177  	      virtual void restore ( const dmtcp::vector<int>&, ConnectionRewirer& );
178  	
179  	      //virtual void doLocking ( const dmtcp::vector<int>& fds );
180  	
181  	      virtual void restoreOptions ( const dmtcp::vector<int>& fds );
182  	
183  	      virtual void doSendHandshakes( const dmtcp::vector<int>& fds, const dmtcp::UniquePid& coordinator);
184  	      virtual void doRecvHandshakes( const dmtcp::vector<int>& fds, const dmtcp::UniquePid& coordinator);
185  	
186  	      void sendHandshake(jalib::JSocket& sock, const dmtcp::UniquePid& coordinator);
187  	      void recvHandshake(jalib::JSocket& sock, const dmtcp::UniquePid& coordinator);
188  	
189  	      const ConnectionIdentifier& getRemoteId() const { return _acceptRemoteId; }
190  	
191  	      //called on restart when _id collides with another connection
192  	      virtual void mergeWith ( const Connection& that );
193  	    private:
194  	      virtual void serializeSubClass ( jalib::JBinarySerializer& o );
195  	      TcpConnection& asTcp();
196  	    private:
197  	      int                     _sockDomain;
198  	      int                     _sockType;
199  	      int                     _sockProtocol;
200  	      int                     _listenBacklog;
201  	#ifdef EXTERNAL_SOCKET_HANDLING
202  	      enum PeerType           _peerType;
203  	#endif
204  	      union {
205  	        socklen_t               _bindAddrlen;
206  	        socklen_t               _connectAddrlen;
207  	      };
208  	      union {
209  	        struct sockaddr_storage _bindAddr;
210  	        struct sockaddr_storage _connectAddr;
211  	      };
212  	      ConnectionIdentifier    _acceptRemoteId;
213  	      dmtcp::map< int, dmtcp::map< int, jalib::JBuffer > > _sockOptions; // _options[level][option] = value
214  	  };
215  	
216  	
217  	  class PtyConnection : public Connection
218  	  {
219  	    public:
220  	      enum PtyType
221  	      {
222  	        PTY_INVALID   = PTY,
223  	        PTY_DEV_TTY,
224  	        PTY_CTTY,
225  	        PTY_MASTER,
226  	        PTY_SLAVE,
227  	        PTY_BSD_MASTER,
228  	        PTY_BSD_SLAVE
229  	
230  	//        TYPEMASK = PTY_CTTY | PTY_Master | PTY_Slave
231  	      };
232  	
233  	      PtyConnection ( const dmtcp::string& ptsName, const dmtcp::string& uniquePtsName, int type )
234  	          : Connection ( PTY )
235  	          , _ptsName ( ptsName )
236  	          , _uniquePtsName ( uniquePtsName )
237  	      {
238  	        _type = type;
239  	        JTRACE("Creating PtyConnection")(ptsName)(uniquePtsName)(id());
240  	        //if ( type != PTY_CTTY &&  filename.compare ( "?" ) == 0 )
241  	        //{
242  	        //  _type = PTY_INVALID;
243  	        //}
244  	      }
245  	
246  	      PtyConnection ( const dmtcp::string& device, int type )
247  	          : Connection ( PTY )
248  	          , _bsdDeviceName ( device )
249  	      {
250  	        _type = type;
251  	        JTRACE("Creating BSDPtyConnection")(device)(id());
Event uninit_member: Non-static class member _ptmxIsPacketMode is not initialized in this constructor nor in any functions that it calls.
Also see events: [member_decl]
252  	      }
253  	
254  	      PtyConnection()
255  	          : Connection ( PTY )
256  	          , _ptsName ( "?" )
257  	          , _uniquePtsName ( "?" )
258  	      {
259  	        _type = PTY_INVALID;
260  	        JTRACE("Creating empty PtyConnection")(id());
261  	      }
262  	
263  	      int  ptyType() { return _type;}// & TYPEMASK ); }
264  	      dmtcp::string ptsName() { return _ptsName;; }
265  	      dmtcp::string uniquePtsName() { return _uniquePtsName;; }
266  	
267  	      //virtual void doLocking ( const dmtcp::vector<int>& fds );
268  	      virtual void preCheckpoint ( const dmtcp::vector<int>& fds
269  	                                   , KernelBufferDrainer& drain );
270  	      virtual void postCheckpoint ( const dmtcp::vector<int>& fds,
271  	                                    bool isRestart = false);
272  	      virtual void restore ( const dmtcp::vector<int>&, ConnectionRewirer& );
273  	      virtual void restoreOptions ( const dmtcp::vector<int>& fds );
274  	
275  	      virtual void serializeSubClass ( jalib::JBinarySerializer& o );
276  	
277  	      //called on restart when _id collides with another connection
278  	      virtual void mergeWith ( const Connection& that );
279  	    private:
280  	      //PtyType   _type;
281  	      dmtcp::string _ptsName;
282  	      dmtcp::string _uniquePtsName;
283  	      dmtcp::string _bsdDeviceName;
Event member_decl: Class member declaration for _ptmxIsPacketMode.
Also see events: [uninit_member]
284  	      bool          _ptmxIsPacketMode;
285  	
286  	  };
287  	
288  	  class StdioConnection : public Connection
289  	  {
290  	    public:
291  	      enum StdioType
292  	      {
293  	        STDIO_IN = STDIO,
294  	        STDIO_OUT,
295  	        STDIO_ERR,
296  	        STDIO_INVALID
297  	      };
298  	
299  	      StdioConnection( int fd ): Connection ( STDIO + fd )
300  	      {
301  	        JTRACE("creating stdio connection")(fd)(id());
302  	        JASSERT( jalib::Between(0, fd, 2) )(fd).Text("invalid fd for StdioConnection");
303  	      }
304  	
305  	      StdioConnection(): Connection ( STDIO_INVALID ) {}
306  	
307  	      virtual void preCheckpoint ( const dmtcp::vector<int>& fds
308  	                                   , KernelBufferDrainer& drain );
309  	      virtual void postCheckpoint ( const dmtcp::vector<int>& fds,
310  	                                    bool isRestart = false);
311  	      virtual void restore ( const dmtcp::vector<int>&, ConnectionRewirer& );
312  	      virtual void restoreOptions ( const dmtcp::vector<int>& fds );
313  	
314  	      virtual void serializeSubClass ( jalib::JBinarySerializer& o );
315  	
316  	      virtual void mergeWith ( const Connection& that );
317  	
318  	      virtual void restartDup2(int oldFd, int newFd);
319  	  };
320  	
321  	  class FileConnection : public Connection
322  	  {
323  	    public:
324  	      enum FileType
325  	      {
326  	        FILE_INVALID = FILE,
327  	        FILE_REGULAR,
328  	        FILE_DELETED
329  	      };
330  	      //called on restart when _id collides with another connection
331  	      virtual void mergeWith ( const Connection& that );
332  	
333  	      inline FileConnection ( const dmtcp::string& path, off_t offset=-1, 
334  	                              int type = FILE_REGULAR )
335  	          : Connection ( FILE )
336  	          , _path ( path )
337  	          , _offset ( offset )
338  	      {
339  	        _type = type;
340  	        JTRACE("New File connection created")(_path);
341  	      }
342  	
343  	      virtual void preCheckpoint ( const dmtcp::vector<int>& fds
344  	                                   , KernelBufferDrainer& drain );
345  	      virtual void postCheckpoint ( const dmtcp::vector<int>& fds,
346  	                                    bool isRestart = false);
347  	
348  	      virtual void restoreOptions ( const dmtcp::vector<int>& fds );
349  	      virtual void restore ( const dmtcp::vector<int>&, ConnectionRewirer& );
350  	
351  	      virtual void serializeSubClass ( jalib::JBinarySerializer& o );
352  	
353  	      dmtcp::string filePath() { return _path; }
354  	
355  	      bool isDupConnection ( const Connection& _that, dmtcp::ConnectionToFds& conToFds );
356  	
357  	      bool fileType() { return _type; }
358  	
359  	    private:
360  	      void saveFile (int fd);
361  	      int  openFile ();
362  	      void refreshPath();
363  	      void handleUnlinkedFile();
364  	      void calculateRelativePath();
365  	      dmtcp::string getSavedFilePath(const dmtcp::string& path);
366  	
367  	      dmtcp::string _path;
368  	      dmtcp::string _rel_path;
369  	      dmtcp::string _ckptFilesDir;
370  	      bool        _checkpointed;
371  	      off_t       _offset;
372  	      struct stat _stat;
373  	  };
374  	
375  	  class FifoConnection : public Connection
376  	  {
377  	    public:
378  	      //called on restart when _id collides with another connection
379  	      virtual void mergeWith ( const Connection& that );
380  	
381  	      inline FifoConnection ( const dmtcp::string& path )
382  	          : Connection ( FIFO )
383  			  , _path ( path )
384  	      {
385  	        dmtcp::string curDir = jalib::Filesystem::GetCWD();
386  	        int offs = _path.find(curDir);
387  	        if( offs < 0 ){
388  		        _rel_path = "*";
389  	        }else{
390  	          offs += curDir.size();
391  	          offs = _path.find('/',offs);
392  	          offs++;
393  	          _rel_path = _path.substr(offs);
394  	        }
395  	        JTRACE("New Fifo connection created")(_path)(_rel_path);
396  			_in_data.clear();
397  	      }
398  	
399  	      virtual void preCheckpoint ( const dmtcp::vector<int>& fds
400  	                                   , KernelBufferDrainer& drain );
401  	      virtual void postCheckpoint ( const dmtcp::vector<int>& fds,
402  	                                    bool isRestart = false);
403  	
404  	      virtual void restoreOptions ( const dmtcp::vector<int>& fds );
405  	      virtual void restore ( const dmtcp::vector<int>&, ConnectionRewirer& );
406  	
407  	      virtual void serializeSubClass ( jalib::JBinarySerializer& o );
408  	
409  	      //virtual void doLocking ( const dmtcp::vector<int>& fds );
410  	
411  	    private:
412  	      int  openFile();
413  	      void refreshPath();
414  	      dmtcp::string getSavedFilePath(const dmtcp::string& path);
415  	      dmtcp::string _path;
416  	      dmtcp::string _rel_path;
417  	      dmtcp::string _savedRelativePath;
418  	      struct stat _stat;
419  	      bool _has_lock;
420  	      vector<char> _in_data;
421  	      int ckptfd;
422  	  };
423  	}
424  	
425  	#endif