gloox 1.0.24
connectiontcpbase.cpp
1/*
2 Copyright (c) 2004-2019 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 <winsock2.h>
26# include <ws2tcpip.h>
27#endif
28
29#if ( !defined( _WIN32 ) && !defined( _WIN32_WCE ) ) || defined( __SYMBIAN32__ )
30# include <arpa/inet.h>
31# include <sys/types.h>
32# include <sys/socket.h>
33# include <sys/select.h>
34# include <netinet/in.h>
35# include <unistd.h>
36# include <string.h>
37# include <errno.h>
38# include <netdb.h>
39#elif ( defined( _WIN32 ) || defined( _WIN32_WCE ) ) && !defined( __SYMBIAN32__ )
40# include <winsock2.h>
41# include <ws2tcpip.h>
42typedef int socklen_t;
43#endif
44
45#include <ctime>
46
47#include <cstdlib>
48#include <string>
49
50namespace gloox
51{
52
54 const std::string& server, int port )
55 : ConnectionBase( 0 ),
56 m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
57 m_totalBytesOut( 0 ), m_bufsize( 8192 ), m_cancel( true )
58 {
59 init( server, port );
60 }
61
63 const std::string& server, int port )
64 : ConnectionBase( cdh ),
65 m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
66 m_totalBytesOut( 0 ), m_bufsize( 8192 ), m_cancel( true )
67 {
68 init( server, port );
69 }
70
71 void ConnectionTCPBase::init( const std::string& server, int port )
72 {
73// FIXME check return value?
75 m_port = port;
76 m_buf = static_cast<char*>( calloc( m_bufsize + 1, sizeof( char ) ) );
77 }
78
80 {
81 cleanup();
82 free( m_buf );
83 m_buf = 0;
84 }
85
87 {
88 util::MutexGuard rm( m_recvMutex );
89 m_cancel = true;
90 }
91
92 bool ConnectionTCPBase::dataAvailable( int timeout )
93 {
94 if( m_socket < 0 )
95 return true; // let recv() catch the closed fd
96
97 fd_set fds;
98 struct timeval tv;
99
100 FD_ZERO( &fds );
101 // the following causes a C4127 warning in VC++ Express 2008 and possibly other versions.
102 // however, the reason for the warning can't be fixed in gloox.
103 FD_SET( m_socket, &fds );
104
105 tv.tv_sec = timeout / 1000000;
106 tv.tv_usec = timeout % 1000000;
107
108 return ( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 )
109 && FD_ISSET( m_socket, &fds ) != 0 );
110 }
111
113 {
114 if( m_socket < 0 )
115 return ConnNotConnected;
116
118 while( !m_cancel && ( err = recv( 1000000 ) ) == ConnNoError )
119 ;
120 return err == ConnNoError ? ConnNotConnected : err;
121 }
122
123 bool ConnectionTCPBase::send( const std::string& data )
124 {
125 m_sendMutex.lock();
126
127 if( data.empty() || ( m_socket < 0 ) )
128 {
129 m_sendMutex.unlock();
130 return false;
131 }
132
133 int sent = 0;
134 for( size_t num = 0, len = data.length(); sent != -1 && num < len; num += sent )
135 {
136 sent = static_cast<int>( ::send( m_socket, (data.c_str()+num), static_cast<int>( len - num ), 0 ) );
137 }
138
139 m_totalBytesOut += data.length();
140
141 m_sendMutex.unlock();
142
143 if( sent == -1 )
144 {
145 // send() failed for an unexpected reason
146 std::string message = "send() failed. "
147#if defined( _WIN32 ) && !defined( __SYMBIAN32__ )
148 "WSAGetLastError: " + util::int2string( ::WSAGetLastError() );
149#else
150 "errno: " + util::int2string( errno ) + ": " + strerror( errno );
151#endif
152 m_logInstance.err( LogAreaClassConnectionTCPBase, message );
153
154 if( m_handler )
156 }
157
158 return sent != -1;
159 }
160
161 void ConnectionTCPBase::getStatistics( long int &totalIn, long int &totalOut )
162 {
163 totalIn = m_totalBytesIn;
164 totalOut = m_totalBytesOut;
165 }
166
168 {
169 if( !m_sendMutex.trylock() )
170 return;
171
172 if( !m_recvMutex.trylock() )
173 {
174 m_sendMutex.unlock();
175 return;
176 }
177
178 if( m_socket >= 0 )
179 {
180 DNS::closeSocket( m_socket, m_logInstance );
181 m_socket = -1;
182 }
183
185 m_cancel = true;
186 m_totalBytesIn = 0;
187 m_totalBytesOut = 0;
188
189 m_recvMutex.unlock(),
190 m_sendMutex.unlock();
191 }
192
194 {
195 struct sockaddr local;
196 socklen_t len = static_cast<socklen_t>( sizeof( local ) );
197 if( getsockname ( m_socket, &local, &len ) < 0 )
198 return -1;
199 else
200 return ntohs( (reinterpret_cast<struct sockaddr_in*>( &local ) )->sin_port );
201 }
202
203 const std::string ConnectionTCPBase::localInterface() const
204 {
205 struct sockaddr_storage local;
206 socklen_t len = static_cast<socklen_t>( sizeof( local ) );
207 if( getsockname( m_socket, reinterpret_cast<struct sockaddr*>( &local ), &len ) < 0 )
208 return EmptyString;
209 else
210 {
211 char buffer[INET6_ADDRSTRLEN];
212 int err = getnameinfo( reinterpret_cast<struct sockaddr*>( &local ), len, buffer, sizeof( buffer ),
213 0, 0, NI_NUMERICHOST );
214 if( !err )
215 return buffer;
216 else
217 return EmptyString;
218 }
219 }
220
221}
An abstract base class for a connection.
ConnectionState m_state
const std::string & server() const
virtual ConnectionError recv(int timeout=-1)=0
ConnectionDataHandler * m_handler
This is an abstract base class to receive events from a ConnectionBase-derived object.
virtual void handleDisconnect(const ConnectionBase *connection, ConnectionError reason)=0
virtual const std::string localInterface() const
ConnectionTCPBase(const LogSink &logInstance, const std::string &server, int port=-1)
virtual int localPort() const
virtual bool send(const std::string &data)
virtual ConnectionError receive()
virtual void getStatistics(long int &totalIn, long int &totalOut)
static void closeSocket(int fd, const LogSink &logInstance)
Definition: dns.cpp:518
An implementation of log sink and source.
Definition: logsink.h:39
void err(LogArea area, const std::string &message) const
Definition: logsink.h:84
A simple implementation of a mutex guard.
Definition: mutexguard.h:32
bool idna(const std::string &domain, std::string &out)
Definition: prep.cpp:107
The namespace for the gloox library.
Definition: adhoc.cpp:28
ConnectionError
Definition: gloox.h:684
@ ConnNotConnected
Definition: gloox.h:715
@ ConnNoError
Definition: gloox.h:685
@ ConnIoError
Definition: gloox.h:696
@ LogAreaClassConnectionTCPBase
Definition: gloox.h:1055
const std::string EmptyString
Definition: gloox.cpp:124
@ StateDisconnected
Definition: gloox.h:642