gloox  1.0.1
connectiontcpclient.cpp
1 /*
2  Copyright (c) 2004-2012 by Jakob Schroeter <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 "connectiontcpclient.h"
18 #include "dns.h"
19 #include "logsink.h"
20 #include "mutexguard.h"
21 #include "util.h"
22 
23 #ifdef __MINGW32__
24 # include <winsock.h>
25 #endif
26 
27 #if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
28 # include <sys/types.h>
29 # include <sys/socket.h>
30 # include <sys/select.h>
31 # include <unistd.h>
32 # include <string.h>
33 # include <errno.h>
34 #elif ( defined( _WIN32 ) || defined( _WIN32_WCE ) ) && !defined( __SYMBIAN32__ )
35 # include <winsock.h>
36 #endif
37 
38 #include <cstdlib>
39 #include <string>
40 
41 namespace gloox
42 {
43 
45  const std::string& server, int port )
46  : ConnectionTCPBase( logInstance, server, port )
47  {
48  }
49 
51  const std::string& server, int port )
52  : ConnectionTCPBase( cdh, logInstance, server, port )
53  {
54  }
55 
56 
58  {
59  }
60 
62  {
63  return new ConnectionTCPClient( m_handler, m_logInstance, m_server, m_port );
64  }
65 
67  {
68  m_sendMutex.lock();
69 // FIXME CHECKME
70  if( !m_handler )
71  {
72  m_sendMutex.unlock();
73  return ConnNotConnected;
74  }
75 
76  if( m_socket >= 0 && m_state > StateDisconnected )
77  {
78  m_sendMutex.unlock();
79  return ConnNoError;
80  }
81 
83 
84  if( m_socket < 0 )
85  {
86  if( m_port == -1 )
87  m_socket = DNS::connect( m_server, m_logInstance );
88  else
89  m_socket = DNS::connect( m_server, m_port, m_logInstance );
90  }
91 
92  m_sendMutex.unlock();
93 
94  if( m_socket < 0 )
95  {
96  switch( m_socket )
97  {
99  m_logInstance.err( LogAreaClassConnectionTCPClient,
100  m_server + ": connection refused" );
101  break;
102  case -ConnDnsError:
103  m_logInstance.err( LogAreaClassConnectionTCPClient,
104  m_server + ": host not found" );
105  break;
106  default:
107  m_logInstance.err( LogAreaClassConnectionTCPClient,
108  "Unknown error condition" );
109  break;
110  }
111  m_handler->handleDisconnect( this, (ConnectionError)-m_socket );
112  return (ConnectionError)-m_socket;
113  }
114  else
115  {
117  }
118 
119  m_cancel = false;
120  m_handler->handleConnect( this );
121  return ConnNoError;
122  }
123 
125  {
126  m_recvMutex.lock();
127 
128  if( m_cancel || m_socket < 0 )
129  {
130  m_recvMutex.unlock();
131  return ConnNotConnected;
132  }
133 
134  if( !dataAvailable( timeout ) )
135  {
136  m_recvMutex.unlock();
137  return ConnNoError;
138  }
139 
140  int size = static_cast<int>( ::recv( m_socket, m_buf, m_bufsize, 0 ) );
141  if( size > 0 )
142  m_totalBytesIn += size;
143 
144  m_recvMutex.unlock();
145 
146  if( size <= 0 )
147  {
148  if( size == -1 )
149  {
150  // recv() failed for an unexpected reason
151  std::string message = "recv() failed. "
152 #if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
153  "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
154 #else
155  "errno: " + util::int2string( errno ) + ": " + strerror( errno );
156 #endif
157  m_logInstance.err( LogAreaClassConnectionTCPClient, message );
158  }
159 
160  ConnectionError error = ( size ? ConnIoError : ConnStreamClosed );
161  if( m_handler )
162  m_handler->handleDisconnect( this, error );
163  return error;
164  }
165 
166  m_buf[size] = '\0';
167 
168  if( m_handler )
169  m_handler->handleReceivedData( this, std::string( m_buf, size ) );
170 
171  return ConnNoError;
172  }
173 
174 }