HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_NetSocket.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_NetSocket.h ( UT Library, C++)
7  *
8  * COMMENTS:
9  * Simple Network socket definition. Non-Blocking by default.
10  *
11  */
12 
13 #ifndef __UT_NetSocket__
14 #define __UT_NetSocket__
15 
16 #include "UT_API.h"
17 
18 #include "UT_UniquePtr.h"
19 
20 #include <SYS/SYS_Time.h>
21 
22 // For fd_set, you will need to #include <SYS/SYS_Socket.h>
23 #ifdef WIN32
24 struct fd_set;
25 #endif
26 
27 class UT_String;
28 class UT_WorkBuffer;
29 
30 
32 {
33 public:
34  enum
35  {
36  UT_CONNECT_SUCCESS = 0,
37 
38  UT_WOULD_BLOCK = -1,
39  UT_BAD_ADDRESS = -2,
40  UT_CONNECT_FAILED = -3,
41  UT_ERROR_OCCURED = -4,
42  UT_WRONG_SOCKET = -5,
43  UT_NO_CONNECTION = -6
44  };
45 
46  enum
47  {
48  UT_SHUTDOWN_RECEIVE = 0,
49  UT_SHUTDOWN_SEND = 1,
50  UT_SHUTDOWN_BOTH = 2
51  };
52 
54  UT_NetSocket& operator=(UT_NetSocket& sock);
55 
56  /// Convertes the enum of UT_CONNECT_SUCCESS, etc, into an english
57  /// error message roughly matching the enum's name. Be careful
58  /// as this uses different errors different locations.
59  static const char *getErrorName(int code);
60 
61  static int getPortByService(const char *service, const char *proto="tcp",
62  int default_port = 0);
63 
64  static void getHostName(char *name, int max);
65 
66  // Get the host address of the form xxx.xxx.xxx.xxx. Returns 1 on success
67  static int getHostAddress(unsigned char address[4],
68  const char *hostname = 0);
69 
70  // Obtains the actual machine name of the host specified by
71  // alias name. Return true on success. If alias = 0, obtains local machine.
72  static bool getHostNameByAlias(UT_String &host, const char *alias = NULL);
73 
74  // Try to map a port number into the range of unprivileged port numbers.
75  static int mapToUnprivilegedPort(int port);
76 
77  // This convenience method can be called from external programs to send
78  // a command on a socket port and wait for a response. If the host name
79  // is null, the local host will be used. If remap_privileged_ports is
80  // true, the given port might be remapped to increase the likelihood
81  // of it being opened. False will be returned if the socket could not be
82  // opened.
83  static bool sendCommandAndGetResult(int port,
84  const char *command,
85  UT_WorkBuffer &response,
86  const char *host_name = 0,
87  bool remap_privileged_ports = true);
88 
89  static bool nonBlockingSendCommandAndGetResult(int port,
90  const char *command,
91  UT_WorkBuffer &response,
92  const char *host_name = 0,
93  bool remap_privileged_ports = true);
94 
95  /// Creates a new listen socket on the specified port. A port of 0
96  /// will auto-choose a free port. Be careful overusing that, however,
97  /// as Windows in particular has very few ports available by default.
98  /// portisonlyhint will attempt to bind to the given port but if
99  /// it fails (ie, already in use) will revert to using 0 to select
100  /// a free port. The caller should thus double check the actual
101  /// bound port if they care.
102  static UT_NetSocket *newSocket(int port, bool blocking = false,
103  bool portisonlyhint = false);
104  static UT_NetSocket *newSocketFromAddr(
105  const char *address,
106  int port,
107  bool blocking = false,
108  int localport = -1,
109  int forcesocket=0);
110  static void fdZero(fd_set *set);
111  static void fdSet(int fd, fd_set *set);
112  static void fdClr(int fd, fd_set *set);
113  static int fdIsSet(int fd, fd_set *set);
114 
115  /// Performs a select() call on the socket.
116  ///
117  ///
118  /// Note, it turns out there is a discrepancy between how select() works on
119  /// Linux vs. Windows.
120  ///
121  /// On Windows, the select() call selects for reading the sockets even if
122  /// they were closed by the remote counterparts. The rationale is that
123  /// trying to read from such a socket returns zero, which is a signal that
124  /// the connection was closed.
125  ///
126  /// On Linux/OSX, select() call does not select such sockets for reading.
127  /// The rationale is that there cannot be any more data for reading on
128  /// closed sockets.
129  ///
130  ///
131  /// WARNING: the following select will not work on UT_PipeSocket instance
132  /// for write and error sets because there is no system call that probes
133  /// these states. UT_PipeSocket derives from UT_NetSocket, so be careful
134  ///
135  /// Use it only on sockets!
136  static int select(int fd, fd_set *r_set, fd_set *w_set,
137  fd_set *e_set, SYS_TimeVal *tv,
138  bool forcesocket=false);
139  // Simplified select which takes a timeout in milliseconds
140  static int selectInMS(int maxfd,
141  fd_set *r_set,
142  fd_set *w_set,
143  fd_set *e_set,
144  int timeoutms = 0,
145  bool forcesocket = false);
146 
147  bool isSocketSelected(fd_set &set);
148  // Adds this socket to the given fd set.
149  void addToFDSet(fd_set *set, int &maxfd);
150 
151  // Destructor. Closes connection if open.
152  virtual ~UT_NetSocket();
153 
154  virtual int64 getMemoryUsage(bool inclusive) const;
155 
156  // *******************************************************
157  // Connection routines
158 
159  // Determines if any connection requests are pending, and creates a
160  // new socket for that connection (SERVER SOCKET ONLY).
161  virtual UT_NetSocket *accept(int blocking, int &condition);
162 
163  // Connects to the server named in the constructor (CLIENT SOCKET ONLY)
164  // If timeout is greater than zero, the connection time is going to be
165  // no longer than the amount specified. If connection succeeds within
166  // the time specified, UT_CONNECT_SUCCESS is returned. If timeout is
167  // zero, a blocking connectoin is carried out, and if fails UT_WOULD_BLOCK
168  // or UT_CONNECT_FAILED is returned.
169  virtual int connect(int timeout_ms = 0);
170 
171  // closes the socket (client or server).
172  virtual int close();
173 
174  virtual int shutdown(int type);
175 
176  // *******************************************************
177  // I/O Routines (client or server)
178 
179  // writes len bytes to the socket.
180  virtual int write(const void *data,int len,int *numWritten = 0);
181 
182  // peeks to see if any data is available. Timeout is specified in ms.
183  // Returns 1 if there is data to be read, 0 if not, and less
184  // than 0 if error.
185  virtual int dataAvailable(int timeout=0);
186 
187  // Attempts to read len bytes. Actual number of read bytes is
188  // returned in numRead.
189  // If read ever succeeds, UT_CONNECT_SUCCESS is returned.
190  // If any error ever occurs during a read, UT_ERROR_OCCURED is returned.
191  // If specified timeout_ms is non-negative then read will block
192  // for at most that many miliseconds, and then it will return
193  // UT_WOULD_BLOCK if still no data has been read.
194  // If UT_WOULD_BLOCK is returned, numRead may be non-zero to
195  // show that some data was read prior to the block.
196  // If specified timeout_ms is less than zero, a blocking socket will
197  // block (wait) till data is available, and a non blocking socket
198  // will return right away with UT_WOULD_BLOCK code.
199  virtual int read(void *data, int len, int *numRead = 0,
200  int timeout_ms = -1);
201 
202  // Read all available data into a work buffer.
203  virtual int read(UT_WorkBuffer &data, int timeout_ms = -1,
204  bool wait_for_null_terminator = false);
205 
206  // Reads len bytes & doesn't remove them from the queue
207  virtual int peek(void *data, int len, int timeout_ms = -1);
208 
209  // Flushes the read or write queue.
210  virtual int flushRead();
211  virtual int flushWrite();
212 
213  void terminateOnConnectionLost(bool term = true);
214 
215  // ********************************************************
216  // Miscellaneous routines.
217 
218  // returns the address name and port of the host, or the connected
219  // host (in the case of a UT_NetSocket returned by accept().)
220 
221  const char *getAddress() const
222  { return myAddressName ? myAddressName:""; }
223 
224  int getPort() const
225  { return myAddressPort; }
226 
227  // Returns information about the other end of the socket. "host" buffer
228  // must be at least 20 characters longs.
229  virtual int getRemoteSocket(char *host, int &port) const;
230 
231  // Sets the socket to blocking or non blocking
232  virtual int setBlocking(bool blocking);
233  bool isBlocking() const { return myIsBlocking; }
234 
235  void setNoDelay(int usenodelay);
236  // Note: This is transitory on a socket, it will be reset by deep
237  // unknowable magic in the kernel. It also is only supported on
238  // some platforms.
239  void setQuickAck(int quickack);
240 
241  // true if the socket is valid.
242  virtual int isValid();
243 
244  // true if the socket is a server socket
245  bool isServer() const { return myIsServer; }
246  // true if the socket is connected.
247  int isConnected();
248 
249  // returns the file descriptor for the socket... beware!
250  int getSocket() const;
251 
252  uint32 getRemoteIP4() const { return myRemoteIP4; }
253  bool getRemoteIP4(int ip[4]);
254  uint32 getLocalIP4() const;
255  bool getLocalIP4(int ip[4]);
256 
257 protected:
258  // Method to construct UT_NetSocket object without knowing its underlying
259  // type. This is used for ::accept().
261  int socket, bool blocking)
262  {
263  return UT_UniquePtr<UT_NetSocket>(new UT_NetSocket(sock, socket, blocking));
264  }
265 
266  // Because virtuals shouldn't be called in destructors, we have a
267  // non-virtual close method.
268  int closeInetSocket();
269 
270  // The actual net-socket constructors
271  UT_NetSocket(UT_NetSocket *netsocket, int socket, bool blocking);
272  UT_NetSocket(int port, bool blocking = false, bool portisonlyhint=false);
273  UT_NetSocket(const char *address, int port, bool blocking = false,
274  int localport = -1);
275 
276  // Default constructor used by shmsocket stuff
277  UT_NetSocket(); // Default
278 
279  // Helper method for waiting for data on the socket or a timeout.
280  // It is really a wrapper for data available with extra error checks
281  // Returns UT_NO_CONNECTION, UT_ERROR_OCCURED if error,
282  // UT_WOULD_BLOCK if timeout expired, or UT_CONNECTION_SUCCESS if
283  // specified timeout <= 0 or if data is available before timeout expired.
284  int waitForDataOrTimeout( int timeout_ms );
285 
286 private:
287  // helper method that implements a timed-out connection for sockets
288  // (especially, NOT FOR PIPES ON NT!)
289  // Returns the errno of the socket (eg, 0 if OK, ETIMEDOUT if timeout, ...)
290  int connectOrTimeout(struct sockaddr_in *address,
291  int address_length, int timeout_ms);
292 
293  // platform dependent code for API
294  // Returns 0 if OK, or errno if failed
295  int doConnect(struct sockaddr_in *address,
296  int address_length, bool check_err);
297 
298  // probes the activity of this socket for read, write, error readines
299  // (whichever is not NULL) and sets the given argument appropriately.
300  // Returns 0 if timeout, 1 if OK, negative if error.
301  // NB: this call is used by UT_NetPacket::connect() during the connection
302  // process. It is applicable only to UT_NetSocket, and is not
303  // to UT_PipeSocket which derives from UT_NetSocket. The reason is
304  // that pipe cannot test fd_write or fd_error, which may be essential
305  // during connection process implemented by this class. UT_PipeSocket
306  // has own connect() method that does not use checkConnectStatus()
307  int checkDataStatus(bool *fd_read, bool *fd_write,
308  bool *fd_error, int timeout_ms);
309 
310  // abstracted host by alias part that is common to Linux and NT
311  static bool commonGetHostNameByAlias( UT_String &host,
312  const char *alias );
313 
314 protected:
315 
318  int mySocket;
319  uint32 myRemoteIP4; // Remote IP address
320 
321  //flags
322  unsigned char myIsServer :1,
323  myConnected :1,
324  myShmFlag :1, // Am I a shared memory socket?
325  myTermOnLost :1, // exit if connection broken.
326  myIsBlocking :1;
327 };
328 
330 {
331 public:
332  UT_AutoSocketDeleter(UT_NetSocket *socket) : mySocket(socket) {}
333  ~UT_AutoSocketDeleter() { delete mySocket; }
334 private:
335  UT_NetSocket *mySocket;
336 };
337 
338 #endif
struct timeval SYS_TimeVal
Definition: SYS_Time.h:27
uint32 myRemoteIP4
Definition: UT_NetSocket.h:319
vint4 max(const vint4 &a, const vint4 &b)
Definition: simd.h:4703
uint32 getRemoteIP4() const
Definition: UT_NetSocket.h:252
GLuint const GLchar * name
Definition: glew.h:1814
int getPort() const
Definition: UT_NetSocket.h:224
char * myAddressName
Definition: UT_NetSocket.h:316
#define UT_API
Definition: UT_API.h:13
void read(T &in, bool &v)
Definition: ImfXdr.h:611
GLuint GLuint64EXT address
Definition: glew.h:14600
GLenum condition
Definition: glew.h:12785
long long int64
Definition: SYS_Types.h:111
virtual UT_UniquePtr< UT_NetSocket > createInstance(UT_NetSocket *sock, int socket, bool blocking)
Definition: UT_NetSocket.h:260
vint4 select(const vbool4 &mask, const vint4 &a, const vint4 &b)
Definition: simd.h:4678
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1379
const char * getAddress() const
Definition: UT_NetSocket.h:221
bool isBlocking() const
Definition: UT_NetSocket.h:233
GLuint GLuint GLsizei GLenum type
Definition: glew.h:1253
bool isServer() const
Definition: UT_NetSocket.h:245
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:47
virtual void close()
GLbitfield GLuint64 timeout
Definition: glew.h:6605
void write(T &out, bool v)
Definition: ImfXdr.h:332
UT_AutoSocketDeleter(UT_NetSocket *socket)
Definition: UT_NetSocket.h:332
GLenum GLsizei len
Definition: glew.h:7752
unsigned int uint32
Definition: SYS_Types.h:40