gloox  0.9.9.12
connectiontcpbase.cpp
1 /*
2  Copyright (c) 2004-2008 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 "connectiontcpbase.h"
18 #include "dns.h"
19 #include "logsink.h"
20 #include "prep.h"
21 #include "mutexguard.h"
22 
23 #ifdef __MINGW32__
24 # include <winsock.h>
25 #endif
26 
27 #if !defined( _WIN32 ) && !defined( _WIN32_WCE )
28 # include <sys/types.h>
29 # include <sys/socket.h>
30 # include <sys/select.h>
31 # include <unistd.h>
32 #else
33 # include <winsock.h>
34 #endif
35 
36 #include <time.h>
37 
38 #include <cstdlib>
39 #include <string>
40 
41 #ifndef _WIN32_WCE
42 # include <sstream>
43 #endif
44 
45 namespace gloox
46 {
47 
49  const std::string& server, int port )
50  : ConnectionBase( 0 ),
51  m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
52  m_totalBytesOut( 0 ), m_bufsize( 1024 ), m_cancel( true )
53  {
54  init( server, port );
55  }
56 
58  const std::string& server, int port )
59  : ConnectionBase( cdh ),
60  m_logInstance( logInstance ), m_buf( 0 ), m_socket( -1 ), m_totalBytesIn( 0 ),
61  m_totalBytesOut( 0 ), m_bufsize( 1024 ), m_cancel( true )
62  {
63  init( server, port );
64  }
65 
66  void ConnectionTCPBase::init( const std::string& server, int port )
67  {
68  m_server = prep::idna( server );
69  m_port = port;
70  m_buf = (char*)calloc( m_bufsize + 1, sizeof( char ) );
71  }
72 
74  {
75  cleanup();
76  free( m_buf );
77  m_buf = 0;
78  }
79 
81  {
82  MutexGuard rm( m_recvMutex );
83  m_cancel = true;
84  }
85 
86  bool ConnectionTCPBase::dataAvailable( int timeout )
87  {
88  if( m_socket < 0 )
89  return true; // let recv() catch the closed fd
90 
91  fd_set fds;
92  struct timeval tv;
93 
94  FD_ZERO( &fds );
95  FD_SET( m_socket, &fds );
96 
97  tv.tv_sec = timeout / 1000000;
98  tv.tv_usec = timeout % 1000000;
99 
100  return ( ( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) > 0 )
101  && FD_ISSET( m_socket, &fds ) != 0 );
102  }
103 
105  {
106  if( m_socket < 0 )
107  return ConnNotConnected;
108 
110  while( !m_cancel && ( err = recv( 10 ) ) == ConnNoError )
111  ;
112  return err == ConnNoError ? ConnNotConnected : err;
113  }
114 
115  bool ConnectionTCPBase::send( const std::string& data )
116  {
117  m_sendMutex.lock();
118 
119  if( data.empty() || ( m_socket < 0 ) )
120  {
121  m_sendMutex.unlock();
122  return false;
123  }
124 
125  int sent = 0;
126  for( size_t num = 0, len = data.length(); sent != -1 && num < len; num += sent )
127  {
128 #ifdef SKYOS
129  sent = ::send( m_socket, (unsigned char*)(data.c_str()+num), len - num, 0 );
130 #else
131  sent = ::send( m_socket, (data.c_str()+num), len - num, 0 );
132 #endif
133  }
134 
135  m_totalBytesOut += data.length();
136 
137  m_sendMutex.unlock();
138 
139  if( sent == -1 && m_handler )
140  m_handler->handleDisconnect( this, ConnIoError );
141 
142  return sent != -1;
143  }
144 
145  void ConnectionTCPBase::getStatistics( int &totalIn, int &totalOut )
146  {
147  totalIn = m_totalBytesIn;
148  totalOut = m_totalBytesOut;
149  }
150 
152  {
153  if( m_socket >= 0 )
154  {
155  DNS::closeSocket( m_socket );
156  m_socket = -1;
157  }
158 
159  MutexGuard sm( m_sendMutex );
160  MutexGuard rm( m_recvMutex );
161  m_state = StateDisconnected;
162  m_cancel = true;
163  m_totalBytesIn = 0;
164  m_totalBytesOut = 0;
165  }
166 
167 }