]> git.donarmstrong.com Git - bamtools.git/blob - src/api/internal/io/TcpSocketEngine_p.cpp
Fixed: premature EOF issues & updated Windows implementation
[bamtools.git] / src / api / internal / io / TcpSocketEngine_p.cpp
1 // ***************************************************************************
2 // TcpSocketEngine_p.cpp (c) 2011 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 8 December 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides low-level implementation of TCP I/O
8 // ***************************************************************************
9
10 // N.B. - this file contains the top-level, platform-independent logic. "Native" methods
11 //        are called as needed from the TcpSocketEngine_<X>.cpp files. Selection of the proper
12 //        native method file should have been handled at build-time by CMake.
13
14 #include "api/internal/io/HostInfo_p.h"
15 #include "api/internal/io/TcpSocketEngine_p.h"
16
17 using namespace BamTools;
18 using namespace BamTools::Internal;
19
20 TcpSocketEngine::TcpSocketEngine(void)
21     : m_socketDescriptor(-1)
22 //    , m_localPort(0)
23     , m_remotePort(0)
24     , m_socketError(TcpSocket::UnknownSocketError)
25     , m_socketState(TcpSocket::UnconnectedState)
26 { }
27
28 TcpSocketEngine::TcpSocketEngine(const TcpSocketEngine& other)
29     : m_socketDescriptor(other.m_socketDescriptor)
30 //    , m_localAddress(other.m_localAddress)
31     , m_remoteAddress(other.m_remoteAddress)
32 //    , m_localPort(other.m_localPort)
33     , m_remotePort(other.m_remotePort)
34     , m_socketError(other.m_socketError)
35     , m_socketState(other.m_socketState)
36     , m_errorString(other.m_errorString)
37 { }
38
39 TcpSocketEngine::~TcpSocketEngine(void) {
40     Close();
41 }
42
43 void TcpSocketEngine::Close(void) {
44
45     // close socket if we have valid FD
46     if ( m_socketDescriptor != -1 ) {
47         nativeClose();
48         m_socketDescriptor = -1;
49     }
50
51     // reset state
52     m_socketState = TcpSocket::UnconnectedState;
53 //    m_localAddress.Clear();
54     m_remoteAddress.Clear();
55 //    m_localPort = 0;
56     m_remotePort = 0;
57 }
58
59 bool TcpSocketEngine::Connect(const HostAddress& address, const uint16_t port) {
60
61     // return failure if invalid FD or already connected
62     if ( !IsValid() || (m_socketState == TcpSocket::ConnectedState) ) {
63         // TODO: set error string
64         return false;
65     }
66
67     // attempt to connect to host address on requested port
68     if ( !nativeConnect(address, port) ) {
69         // TODO: set error string
70         return false;
71     }
72
73     // if successful, store remote host address port & return success
74     // TODO: (later) fetch proxied remote & local host/port  here
75     m_remoteAddress = address;
76     m_remotePort    = port;
77     return true;
78 }
79
80 std::string TcpSocketEngine::GetErrorString(void) const {
81     return m_errorString;
82 }
83
84 //HostAddress TcpSocketEngine::GetLocalAddress(void) const {
85 //    return m_localAddress;
86 //}
87
88 //uint16_t TcpSocketEngine::GetLocalPort(void) const {
89 //    return m_localPort;
90 //}
91
92 HostAddress TcpSocketEngine::GetRemoteAddress(void) const {
93     return m_remoteAddress;
94 }
95
96 uint16_t TcpSocketEngine::GetRemotePort(void) const {
97     return m_remotePort;
98 }
99
100 int TcpSocketEngine::GetSocketDescriptor(void) const {
101     return m_socketDescriptor;
102 }
103
104 TcpSocket::SocketError TcpSocketEngine::GetSocketError(void) {
105     return m_socketError;
106 }
107
108 TcpSocket::SocketState TcpSocketEngine::GetSocketState(void) {
109     return m_socketState;
110 }
111
112 bool TcpSocketEngine::Initialize(HostAddress::NetworkProtocol protocol) {
113
114     // close current socket if we have one open
115     if ( IsValid() )
116         Close();
117
118     // attempt to create new socket
119     return nativeCreateSocket(protocol);
120 }
121
122 bool TcpSocketEngine::IsValid(void) const {
123     return (m_socketDescriptor != -1);
124 }
125
126 int64_t TcpSocketEngine::NumBytesAvailable(void) const {
127
128     // return 0 if socket FD is invalid
129     if ( !IsValid() ) {
130         // TODO: set error string
131         return -1;
132     }
133
134     // otherwise check socket to see how much is ready
135     return nativeNumBytesAvailable();
136 }
137
138 int64_t TcpSocketEngine::Read(char* dest, size_t max) {
139
140     // return failure if can't read
141     if ( !IsValid() || (m_socketState != TcpSocket::ConnectedState) )
142         return -1;
143
144     // otherwise return number of bytes read
145     return nativeRead(dest, max);
146 }
147
148 bool TcpSocketEngine::WaitForRead(int msec, bool* timedOut) {
149
150     // reset timedOut flag
151     *timedOut = false;
152
153     // need to wait for our socket to be ready to read
154     const int ret = nativeSelect(msec, true);
155
156     // if timed out
157     if ( ret == 0 ) {
158         *timedOut = true;
159         m_socketError = TcpSocket::SocketTimeoutError;
160         m_errorString = "socket timed out";
161     }
162
163     // return if any sockets available for reading
164     return ( ret > 0 );
165 }
166
167 bool TcpSocketEngine::WaitForWrite(int msec, bool* timedOut) {
168
169     // reset timedOut flag
170     *timedOut = false;
171
172     // need to wait for our socket to be ready to write
173     const int ret = nativeSelect(msec, false);
174
175     // if timed out
176     if ( ret == 0 ) {
177         *timedOut = true;
178         m_socketError = TcpSocket::SocketTimeoutError;
179         m_errorString = "socket timed out";
180     }
181
182     // return if any sockets available for reading
183     return ( ret > 0 );
184 }
185
186 int64_t TcpSocketEngine::Write(const char* data, size_t length) {
187
188     // return failure if can't write
189     if ( !IsValid() || (m_socketState != TcpSocket::ConnectedState) ) {
190         // TODO: set error string
191         return -1;
192     }
193
194     // otherwise return number of bytes written
195     return nativeWrite(data, length);
196 }