gloox  1.0.16
connectiontcpbase.cpp
1 /*
2  Copyright (c) 2004-2015 by Jakob Schröter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 
15 #include "gloox.h"
16 
17 #include "connectiontcpbase.h"
18 #include "dns.h"
19 #include "logsink.h"
20 #include "prep.h"
21 #include "mutexguard.h"
22 #include "util.h"
23 
24 #ifdef __MINGW32__
25 # include <winsock.h>
26 #endif
27 
28 #if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
29 # include <arpa/inet.h>
30 # include <sys/types.h>
31 # include <sys/socket.h>
32 # include <sys/select.h>
33 # include <netinet/in.h>
34 # include <unistd.h>
35 # include <string.h>
36 # include <errno.h>
37 # include <netdb.h>
38 #elif ( defined( _WIN32 ) || defined( _WIN32_WCE ) ) && !defined( __SYMBIAN32__ )
39 # include <winsock.h>
40 typedef int socklen_t;
41 #endif
42 
43 #include <ctime>
44 
45 #include <cstdlib>
46 #include <string>
47 
48 namespace gloox
49 {
50 
52  const std::string& server, int port )
53  : ConnectionBase( 0 ),
54  m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
55  m_totalBytesOut( 0 ), m_bufsize( 8192 ), m_cancel( true )
56  {
57  init( server, port );
58  }
59 
61  const std::string& server, int port )
62  : ConnectionBase( cdh ),
63  m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
64  m_totalBytesOut( 0 ), m_bufsize( 8192 ), m_cancel( true )
65  {
66  init( server, port );
67  }
68 
69  void ConnectionTCPBase::init( const std::string& server, int port )
70  {
71 // FIXME check return value?
72  prep::idna( server, m_server );
73  m_port = port;
74  m_buf = (char*)calloc( m_bufsize + 1, sizeof( char ) );
75  }
76 
78  {
79  cleanup();
80  free( m_buf );
81  m_buf = 0;
82  }
83 
85  {
86  util::MutexGuard rm( m_recvMutex );
87  m_cancel = true;
88  }
89 
90  bool ConnectionTCPBase::dataAvailable( int timeout )
91  {
92  if( m_socket < 0 )
93  return true; // let recv() catch the closed fd
94 
95  fd_set fds;
96  struct timeval tv;
97 
98  FD_ZERO( &fds );
99  // the following causes a C4127 warning in VC++ Express 2008 and possibly other versions.
100  // however, the reason for the warning can't be fixed in gloox.
101  FD_SET( m_socket, &fds );
102 
103  tv.tv_sec = timeout / 1000000;
104  tv.tv_usec = timeout % 1000000;
105 
106  return ( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 )
107  && FD_ISSET( m_socket, &fds ) != 0 );
108  }
109 
111  {
112  if( m_socket < 0 )
113  return ConnNotConnected;
114 
116  while( !m_cancel && ( err = recv( 1000000 ) ) == ConnNoError )
117  ;
118  return err == ConnNoError ? ConnNotConnected : err;
119  }
120 
121  bool ConnectionTCPBase::send( const std::string& data )
122  {
123  m_sendMutex.lock();
124 
125  if( data.empty() || ( m_socket < 0 ) )
126  {
127  m_sendMutex.unlock();
128  return false;
129  }
130 
131  int sent = 0;
132  for( size_t num = 0, len = data.length(); sent != -1 && num < len; num += sent )
133  {
134  sent = static_cast<int>( ::send( m_socket, (data.c_str()+num), (int)(len - num), 0 ) );
135  }
136 
137  m_totalBytesOut += (int)data.length();
138 
139  m_sendMutex.unlock();
140 
141  if( sent == -1 )
142  {
143  // send() failed for an unexpected reason
144  std::string message = "send() failed. "
145 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
146  "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
147 #else
148  "errno: " + util::int2string( errno ) + ": " + strerror( errno );
149 #endif
150  m_logInstance.err( LogAreaClassConnectionTCPBase, message );
151 
152  if( m_handler )
154  }
155 
156  return sent != -1;
157  }
158 
159  void ConnectionTCPBase::getStatistics( long int &totalIn, long int &totalOut )
160  {
161  totalIn = m_totalBytesIn;
162  totalOut = m_totalBytesOut;
163  }
164 
166  {
167  if( !m_sendMutex.trylock() )
168  return;
169 
170  if( !m_recvMutex.trylock() )
171  {
172  m_sendMutex.unlock();
173  return;
174  }
175 
176  if( m_socket >= 0 )
177  {
178  DNS::closeSocket( m_socket, m_logInstance );
179  m_socket = -1;
180  }
181 
183  m_cancel = true;
184  m_totalBytesIn = 0;
185  m_totalBytesOut = 0;
186 
187  m_recvMutex.unlock(),
188  m_sendMutex.unlock();
189  }
190 
192  {
193  struct sockaddr local;
194  socklen_t len = (socklen_t)sizeof( local );
195  if( getsockname ( m_socket, &local, &len ) < 0 )
196  return -1;
197  else
198  return ntohs( ((struct sockaddr_in *)&local)->sin_port );
199  }
200 
201  const std::string ConnectionTCPBase::localInterface() const
202  {
203  struct sockaddr_storage local;
204  socklen_t len = (socklen_t)sizeof( local );
205  if( getsockname ( m_socket, (reinterpret_cast<struct sockaddr*>( &local )), &len ) < 0 )
206  return EmptyString;
207  else
208  {
209  char buffer[INET6_ADDRSTRLEN];
210  int err = getnameinfo( (struct sockaddr*)&local, len, buffer, sizeof( buffer ),
211  0, 0, NI_NUMERICHOST );
212  if( !err )
213  return buffer;
214  else
215  return EmptyString;
216  }
217  }
218 
219 }
An abstract base class for a connection.
virtual ConnectionError receive()
A simple implementation of a mutex guard.
Definition: mutexguard.h:31
static void closeSocket(int fd, const LogSink &logInstance)
Definition: dns.cpp:512
void err(LogArea area, const std::string &message) const
Definition: logsink.h:84
ConnectionError
Definition: gloox.h:679
ConnectionTCPBase(const LogSink &logInstance, const std::string &server, int port=-1)
This is an abstract base class to receive events from a ConnectionBase-derived object.
virtual const std::string localInterface() const
virtual void handleDisconnect(const ConnectionBase *connection, ConnectionError reason)=0
The namespace for the gloox library.
Definition: adhoc.cpp:27
virtual bool send(const std::string &data)
virtual ConnectionError recv(int timeout=-1)=0
bool idna(const std::string &domain, std::string &out)
Definition: prep.cpp:107
ConnectionState m_state
ConnectionDataHandler * m_handler
virtual int localPort() const
An implementation of log sink and source.
Definition: logsink.h:38
const std::string EmptyString
Definition: gloox.cpp:123
virtual void getStatistics(long int &totalIn, long int &totalOut)