gloox  1.0.28
connectiontcpclient.cpp
1 /*
2  Copyright (c) 2004-2023 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 #include "config.h"
15 
16 #include "gloox.h"
17 
18 #include "connectiontcpclient.h"
19 #include "dns.h"
20 #include "logsink.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 <sys/types.h>
30 # include <sys/socket.h>
31 # include <sys/select.h>
32 # include <unistd.h>
33 # include <string.h>
34 # include <errno.h>
35 #elif ( defined( _WIN32 ) || defined( _WIN32_WCE ) ) && !defined( __SYMBIAN32__ )
36 # include <winsock.h>
37 #endif
38 
39 #include <cstdlib>
40 #include <string>
41 
42 namespace gloox
43 {
44 
46  const std::string& server, int port )
47  : ConnectionTCPBase( logInstance, server, port )
48  {
49  }
50 
52  const std::string& server, int port )
53  : ConnectionTCPBase( cdh, logInstance, server, port )
54  {
55  }
56 
57 
59  {
60  }
61 
63  {
64  return new ConnectionTCPClient( m_handler, m_logInstance, m_server, m_port );
65  }
66 
68  {
69  m_sendMutex.lock();
70 // FIXME CHECKME
71  if( !m_handler )
72  {
73  m_sendMutex.unlock();
74  return ConnNotConnected;
75  }
76 
77  if( m_socket >= 0 && m_state > StateDisconnected )
78  {
79  m_sendMutex.unlock();
80  return ConnNoError;
81  }
82 
84 
85  if( m_socket < 0 )
86  {
87  if( m_port == -1 )
88  m_socket = DNS::connect( m_server, m_logInstance );
89  else
90  m_socket = DNS::connect( m_server, m_port, m_logInstance );
91  }
92 
93  m_sendMutex.unlock();
94 
95  if( m_socket < 0 )
96  {
97  switch( m_socket )
98  {
100  m_logInstance.err( LogAreaClassConnectionTCPClient,
101  m_server + ": connection refused" );
102  break;
103  case -ConnDnsError:
104  m_logInstance.err( LogAreaClassConnectionTCPClient,
105  m_server + ": host not found" );
106  break;
107  default:
108  m_logInstance.err( LogAreaClassConnectionTCPClient,
109  "Unknown error condition" );
110  break;
111  }
112  m_handler->handleDisconnect( this, static_cast<ConnectionError>( -m_socket ) );
113  return static_cast<ConnectionError>( -m_socket );
114  }
115  else
116  {
118  }
119 
120  m_cancel = false;
121  m_handler->handleConnect( this );
122  return ConnNoError;
123  }
124 
126  {
127  m_recvMutex.lock();
128 
129  if( m_cancel || m_socket < 0 )
130  {
131  m_recvMutex.unlock();
132  return ConnNotConnected;
133  }
134 
135  if( !dataAvailable( timeout ) )
136  {
137  m_recvMutex.unlock();
138  return ConnNoError;
139  }
140 
141 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
142  int size = static_cast<int>( ::recv( m_socket, m_buf, m_bufsize, 0 ) );
143 #else
144  int size = static_cast<int>( ::recv( m_socket, m_buf, m_bufsize, MSG_DONTWAIT ) );
145 #endif
146  if( size > 0 )
147  m_totalBytesIn += size;
148 
149  m_recvMutex.unlock();
150 
151  if( size <= 0 )
152  {
153  if( size == -1 )
154  {
155 
156 #if defined(__unix__)
157  if( errno == EAGAIN || errno == EWOULDBLOCK )
158  return ConnNoError;
159 #endif
160 
161  // recv() failed for an unexpected reason
162  std::string message = "recv() failed. "
163 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
164  "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
165 #else
166  "errno: " + util::int2string( errno ) + ": " + strerror( errno );
167 #endif
168  m_logInstance.err( LogAreaClassConnectionTCPClient, message );
169  }
170 
171  ConnectionError error = ( size ? ConnIoError : ConnStreamClosed );
172  if( m_handler )
173  m_handler->handleDisconnect( this, error );
174  return error;
175  }
176 
177  m_buf[size] = '\0';
178 
179  if( m_handler )
180  m_handler->handleReceivedData( this, std::string( m_buf, size ) );
181 
182  return ConnNoError;
183  }
184 
185 }
An abstract base class for a connection.
ConnectionState m_state
ConnectionDataHandler * m_handler
This is an abstract base class to receive events from a ConnectionBase-derived object.
virtual void handleReceivedData(const ConnectionBase *connection, const std::string &data)=0
virtual void handleDisconnect(const ConnectionBase *connection, ConnectionError reason)=0
virtual void handleConnect(const ConnectionBase *connection)=0
This is a base class for a simple TCP connection.
virtual ConnectionError recv(int timeout=-1)
virtual ConnectionBase * newInstance() const
virtual ConnectionError connect()
ConnectionTCPClient(const LogSink &logInstance, const std::string &server, int port=-1)
static int connect(const std::string &host, const LogSink &logInstance)
Definition: dns.cpp:247
An implementation of log sink and source.
Definition: logsink.h:39
void err(LogArea area, const std::string &message) const
Definition: logsink.h:84
The namespace for the gloox library.
Definition: adhoc.cpp:28
ConnectionError
Definition: gloox.h:684
@ ConnNotConnected
Definition: gloox.h:715
@ ConnConnectionRefused
Definition: gloox.h:698
@ ConnDnsError
Definition: gloox.h:700
@ ConnNoError
Definition: gloox.h:685
@ ConnStreamClosed
Definition: gloox.h:689
@ ConnIoError
Definition: gloox.h:696
@ LogAreaClassConnectionTCPClient
Definition: gloox.h:1062
@ StateDisconnected
Definition: gloox.h:642
@ StateConnected
Definition: gloox.h:644
@ StateConnecting
Definition: gloox.h:643