1    	/****************************************************************************
2    	 *   Copyright (C) 2006-2008 by Jason Ansel                                 *
3    	 *   jansel@csail.mit.edu                                                   *
4    	 *                                                                          *
5    	 *   This file is part of the JALIB module of DMTCP (DMTCP:dmtcp/jalib).    *
6    	 *                                                                          *
7    	 *  DMTCP:dmtcp/jalib 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 JALIBJSOCKET_H
23   	#define JALIBJSOCKET_H
24   	
25   	#include "stlwrapper.h"
26   	#include "jalloc.h"
27   	#include <sys/types.h>
28   	#include <sys/socket.h>
29   	#include <netinet/in.h>
30   	#include <vector>
31   	#include "jassert.h"
32   	#include <errno.h>
33   	#include <sys/time.h>
34   	#include <time.h>
35   	
36   	namespace jalib
37   	{
38   	
39   	  class JSocket;
40   	
41   	  class JSockAddr
42   	  {
43   	      friend class JSocket;
44   	    public:
45   	#ifdef JALIB_ALLOCATOR
46   	      static void* operator new(size_t nbytes, void* p) { return p; }
47   	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
48   	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
49   	#endif
50   	      JSockAddr ( const char* hostname = NULL );
51   	      static const JSockAddr ANY;
52   	      const struct sockaddr_in* addr() const{return &_addr;}
53   	      socklen_t                 addrlen() const{return sizeof ( sockaddr_in );}
54   	    private:
55   	      struct sockaddr_in _addr;
56   	  };
57   	
58   	
59   	  class JSocket
60   	  {
61   	    public:
62   	#ifdef JALIB_ALLOCATOR
63   	      static void* operator new(size_t nbytes, void* p) { return p; }
64   	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
65   	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
66   	#endif
67   	      ///
68   	      /// Create new socket
69   	  protected: JSocket(); public:
70   	      //so we don't leak FDs
71   	      inline static JSocket Create() { return JSocket(); }
72   	      ///
73   	      /// Use existing socket
74   	      JSocket ( int fd ) : _sockfd ( fd ) {}
75   	
76   	      bool connect ( const JSockAddr& addr, int port );
77   	      bool connect ( const  struct  sockaddr  *addr,  socklen_t addrlen, int port );
78   	      bool bind ( const JSockAddr& addr, int port );
79   	      bool bind ( const  struct  sockaddr  *addr,  socklen_t addrlen );
80   	      bool listen ( int backlog = 32 );
81   	      JSocket accept ( struct sockaddr_storage* remoteAddr = NULL,socklen_t* remoteLen = NULL );
82   	      bool close();
83   	      ssize_t read ( char* buf, size_t len );
84   	      ssize_t write ( const char* buf, size_t len );
85   	      ssize_t readAll ( char* buf, size_t len );
86   	      ssize_t writeAll ( const char* buf, size_t len );
87   	      bool isValid() const;
88   	
89   	      void enablePortReuse();
90   	
91   	      template <typename T>
92   	      JSocket& operator << ( const T& t ) { writeAll ( ( const char* ) &t, sizeof ( T ) ); return *this; }
93   	      template <typename T>
Event tainted_data_argument: Calling function "jalib::JSocket::readAll(char *, unsigned long)" taints parameter "*((char *)t)". [details]
94   	      JSocket& operator >> ( T& t ) { readAll ( ( char* ) &t, sizeof ( T ) ); return *this; }
95   	
96   	      int sockfd() const { return _sockfd; }
97   	      // If socket originally bound to port 0, we need this to find actual port
98   	      int port() const { struct sockaddr_in addr;
99   				 socklen_t addrlen = sizeof(addr);
100  				 if (-1 == getsockname(_sockfd,
101  						 (struct sockaddr *)&addr, &addrlen))
102  				   return -1;
103  				 else
104  				   return (int)ntohs(addr.sin_port);
105  			       }
106  	      operator int () { return _sockfd; }
107  	      void changeFd ( int newFd );
108  	    protected:
109  	      int _sockfd;
110  	  };
111  	
112  	  class JClientSocket : public JSocket
113  	  {
114  	    public:
115  	      JClientSocket ( const JSockAddr& addr, int port )
116  	      {
117  	        if ( !connect ( addr, port ) )
118  	          close();
119  	      }
120  	  };
121  	
122  	  class JServerSocket : public JSocket
123  	  {
124  	    public:
125  	      JServerSocket ( int sockfd ) 
126  	        : JSocket ( sockfd )
127  	      {
128  	        enablePortReuse();
129  	      }
130  	
131  	      JServerSocket ( const JSockAddr& addr, int port, int backlog = 32 )
132  	      {
133  	        enablePortReuse();
134  	        if ( !bind ( addr, port ) || !listen ( backlog ) )
135  	          close();
136  	      }
137  	  };
138  	
139  	  class JReaderInterface
140  	  {
141  	    public:
142  	#ifdef JALIB_ALLOCATOR
143  	      static void* operator new(size_t nbytes, void* p) { return p; }
144  	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
145  	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
146  	#endif
147  	      JReaderInterface ( JSocket& sock ) :_sock ( sock ) {}
148  	      virtual ~JReaderInterface() {}
149  	      virtual bool readOnce() = 0;
150  	      virtual bool hadError() const = 0;
151  	      virtual void reset() = 0;
152  	      virtual bool ready() const = 0;
153  	      virtual const char* buffer() const = 0;
154  	      virtual int bytesRead() const = 0;
155  	
156  	      const JSocket& socket() const{ return _sock; }
157  	      JSocket& socket() { return _sock; }
158  	    protected:
159  	      JSocket _sock;
160  	  };
161  	
162  	  class JChunkReader : public JReaderInterface
163  	  {
164  	    public:
165  	#ifdef JALIB_ALLOCATOR
166  	      static void* operator new(size_t nbytes, void* p) { return p; }
167  	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
168  	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
169  	#endif
170  	      JChunkReader ( JSocket sock, int chunkSize );
171  	      JChunkReader ( const JChunkReader& that );
172  	      ~JChunkReader();
173  	      JChunkReader& operator= ( const JChunkReader& that );
174  	      bool readOnce();
175  	      void readAll();
176  	      void reset();
177  	      bool ready() const { return _length == _read; }
178  	      const char* buffer() const{ return _buffer; }
179  	      bool hadError() const { return _hadError || !_sock.isValid(); }
180  	      int bytesRead() const {return _read;}
181  	    protected:
182  	      char* _buffer;
183  	      int _length;
184  	      int _read;
185  	      bool _hadError;
186  	  };
187  	
188  	  class JWriterInterface
189  	  {
190  	    public:
191  	#ifdef JALIB_ALLOCATOR
192  	      static void* operator new(size_t nbytes, void* p) { return p; }
193  	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
194  	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
195  	#endif
196  	      JWriterInterface ( JSocket& sock ) :_sock ( sock ) {}
197  	      virtual ~JWriterInterface() {}
198  	      virtual bool writeOnce() = 0;
199  	      virtual bool isDone() = 0;
200  	      virtual bool hadError() = 0;
201  	      const JSocket& socket() const{ return _sock; }
202  	      JSocket& socket() { return _sock; }
203  	    protected:
204  	      JSocket _sock;
205  	  };
206  	
207  	  class JChunkWriter : public JWriterInterface
208  	  {
209  	    public:
210  	#ifdef JALIB_ALLOCATOR
211  	      static void* operator new(size_t nbytes, void* p) { return p; }
212  	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
213  	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
214  	#endif
215  	      JChunkWriter ( JSocket sock, const char* buf, int len );
216  	      JChunkWriter ( const JChunkWriter& that );
217  	      ~JChunkWriter();
218  	      jalib::JChunkWriter& operator= ( const JChunkWriter& that );
219  	
220  	      bool isDone();
221  	      bool writeOnce();
222  	      bool hadError();
223  	
224  	    private:
225  	      char* _buffer;
226  	      int _length;
227  	      int _sent;
228  	      bool _hadError;
229  	  };
230  	
231  	
232  	  class JMultiSocketProgram
233  	  {
234  	    public:
235  	#ifdef JALIB_ALLOCATOR
236  	      static void* operator new(size_t nbytes, void* p) { return p; }
237  	      static void* operator new(size_t nbytes) { JALLOC_HELPER_NEW(nbytes); }
238  	      static void  operator delete(void* p) { JALLOC_HELPER_DELETE(p); }
239  	#endif
240  	      virtual ~JMultiSocketProgram() {}
241  	      void addDataSocket ( JReaderInterface* sock );
242  	      void addListenSocket ( const JSocket& sock );
243  	      void monitorSockets ( double timeoutSec = -1 );
244  	      virtual void onData ( JReaderInterface* sock ) = 0;
245  	      virtual void onConnect ( const JSocket& sock, const struct sockaddr* remoteAddr,socklen_t remoteLen ) = 0;
246  	      virtual void onDisconnect ( JReaderInterface* sock ) {};
247  	      void setTimeoutInterval ( double dblTimeout );
248  	      virtual void onTimeoutInterval() {};
249  	      void addWrite ( JWriterInterface* write );
250  	    protected:
251  	      jalib::vector<JReaderInterface*> _dataSockets;
252  	      jalib::vector<JSocket> _listenSockets;
253  	      jalib::vector<JWriterInterface*> _writes;
254  	    private:
255  	      bool timeoutEnabled;
256  	      struct timeval timeoutInterval;
257  	      struct timeval stoptime;
258  	  };
259  	
260  	} //namespace jalib
261  	
262  	#endif