1 // ***************************************************************************
2 // TcpSocketEngine_win_p.cpp (c) 2011 Derek Barnett
3 // Marth Lab, Department of Biology, Boston College
4 // ---------------------------------------------------------------------------
5 // Last modified: 10 November 2011 (DB)
6 // ---------------------------------------------------------------------------
7 // Provides low-level implementation of TCP I/O for all Windows systems
8 // ***************************************************************************
10 #include "api/internal/io/TcpSocketEngine_p.h"
11 #include "api/internal/io/NetWin_p.h"
12 using namespace BamTools;
13 using namespace BamTools::Internal;
18 // ------------------------
19 // static utility methods
20 // ------------------------
26 //void getPortAndAddress(const sockaddr* s, uint16_t& port, HostAddress& address) {
29 // if (s->sa_family == AF_INET6) {
30 // sockaddr_in6* ip6 = (sockaddr_in6*)s;
31 // port = ntohs(ip6->sin6_port);
33 // memcpy(&tmp, &ip6->sin6_addr.in6_addr, sizeof(tmp));
34 // address.SetAddress(tmp);
39 // if ( s->sa_family == AF_INET ) {
40 // sockaddr_in* ip4 = (sockaddr_in*)s;
41 // port = ntohl(ip4->sin_port);
42 // address.SetAddress( ntohl(ip4->sin_addr) );
46 // // should be unreachable
47 // BT_ASSERT_X(false, "TcpSocketEngine::getPortAndAddress() : unknown network protocol ");
51 } // namespace Internal
52 } // namespace BamTools
54 // --------------------------------
55 // TcpSocketEngine implementation
56 // --------------------------------
58 void TcpSocketEngine::nativeClose(void) {
60 // close(m_socketDescriptor);
63 bool TcpSocketEngine::nativeConnect(const HostAddress& address, const uint16_t port) {
65 // setup connection parameters from address/port
66 // sockaddr_in sockAddrIPv4;
67 // sockaddr_in6 sockAddrIPv6;
68 // sockaddr* sockAddrPtr = 0;
69 // BT_SOCKLEN_T sockAddrSize = 0;
72 // if ( address.GetProtocol() == HostAddress::IPv6Protocol ) {
74 // memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
75 // sockAddrIPv6.sin6_family = AF_INET6;
76 // sockAddrIPv6.sin6_port = htons(port);
78 // IPv6Address ip6 = address.GetIPv6Address();
79 // memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
81 // sockAddrSize = sizeof(sockAddrIPv6);
82 // sockAddrPtr = (sockaddr*)&sockAddrIPv6;
86 // else if ( address.GetProtocol() == HostAddress::IPv4Protocol ) {
88 // memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4));
89 // sockAddrIPv4.sin_family = AF_INET;
90 // sockAddrIPv4.sin_port = htons(port);
91 // sockAddrIPv4.sin_addr.s_addr = htonl(address.GetIPv4Address());
93 // sockAddrSize = sizeof(sockAddrIPv4);
94 // sockAddrPtr = (sockaddr*)&sockAddrIPv4;
97 // // unknown (should be unreachable)
98 // else BT_ASSERT_X(false, "TcpSocketEngine::nativeConnect() : unknown network protocol");
100 // // attempt conenction
101 // int connectResult = connect(socketDescriptor, sockAddrPtr, sockAddrSize);
104 // if ( connectResult == -1 ) {
106 // // see what error was encountered
107 // switch ( errno ) {
110 // m_socketState = TcpSocket::ConnectedState;
112 // case ECONNREFUSED:
114 // m_socketError = TcpSocket::ConnectionRefusedError;
115 // m_socketState = TcpSocket::UnconnectedState;
116 // m_errorString = "connection refused";
119 // m_socketError = TcpSocket::NetworkError;
120 // m_errorString = "connection timed out";
122 // case EHOSTUNREACH:
123 // m_socketError = TcpSocket::NetworkError;
124 // m_socketState = TcpSocket::UnconnectedState;
125 // m_errorString = "host unreachable";
128 // m_socketError = TcpSocket::NetworkError;
129 // m_socketState = TcpSocket::UnconnectedState;
130 // m_errorString = "network unreachable";
133 // m_socketError = TcpSocket::NetworkError;
134 // m_errorString = "address already in use";
138 // m_socketError = TcpSocket::SocketAccessError;
139 // m_socketState = TcpSocket::UnconnectedState;
140 // m_errorString = "permission denied";
141 // case EAFNOSUPPORT:
145 // m_socketState = TcpSocket::UnconnectedState;
150 // if ( m_socketState != TcpSocket::ConnectedState )
154 // // otherwise, we should be good
155 // // update state & return success
156 // m_socketState = TcpSocket::ConnectedState;
160 bool TcpSocketEngine::nativeCreateSocket(HostAddress::NetworkProtocol protocol) {
162 // // get protocol value for requested protocol type
163 // const int protocolNum = ( (protocol == HostAddress::IPv6Protocol) ? AF_INET6 : AF_INET );
165 // // attempt to create socket
166 // int socketFd = socket(protocolNum, SOCK_STREAM, IPPROTO_TCP);
168 // // if we fetched an invalid socket descriptor
169 // if ( socketFd <= 0 ) {
171 // // see what error we got
172 // switch ( errno ) {
173 // case EPROTONOSUPPORT:
174 // case EAFNOSUPPORT:
176 // m_socketError = TcpSocket::UnsupportedSocketOperationError;
177 // m_errorString = "protocol not supported";
183 // m_socketError = TcpSocket::SocketResourceError;
184 // m_errorString = "out of resources";
187 // m_socketError = TcpSocket::SocketAccessError;
188 // m_errorString = "permission denied";
198 // // otherwise, store our socket FD & return success
199 // m_socketDescriptor = socketFd;
203 //bool TcpSocketEngine::nativeFetchConnectionParameters(void) {
205 // // reset addresses/ports
206 // m_localAddress.Clear();
207 // m_remoteAddress.Clear();
211 // // skip (return failure) if invalid socket FD
212 // if ( m_socketDescriptor == -1 )
216 // BT_SOCKLEN_T sockAddrSize = sizeof(sa);
218 // // fetch local address info
219 // memset(&sa, 0, sizeof(sa));
220 // if ( getsockname(m_socketDescriptor, &sa, &sockAddrSize) == 0 ) {
221 // getPortAndAddress(&sa, m_localPort, m_localAddress);
223 // else if ( errno == EBADF ) {
224 // m_socketError = TcpSocket::UnsupportedSocketOperationError;
225 // m_errorString = "invalid socket descriptor";
229 // // fetch remote address
230 // if ( getpeername(m_socketDescriptor, &sa, &sockAddrSize) == 0 )
231 // getPortAndAddress(&sa, m_remotePort, m_remoteAddress);
237 size_t TcpSocketEngine::nativeNumBytesAvailable(void) const {
239 // // fetch number of bytes, return 0 on error
241 // if ( ioctl(m_socketDescriptor, FIONREAD, (char*)&numBytes) < 0 )
243 // return static_cast<size_t>(numBytes);
246 int64_t TcpSocketEngine::nativeRead(char* dest, size_t max) {
251 // ssize_t ret = read(m_socketDescriptor, dest, max);
254 // switch ( errno ) {
256 // // No data was available for reading
267 // return static_cast<int64_t>(ret);
270 // negative value for msecs will block (forever) until
271 int TcpSocketEngine::nativeSelect(int msecs, bool isRead) const {
276 // FD_SET(m_socketDescriptor, &fds);
278 // // setup our timeout
280 // tv.tv_sec = msecs / 1000;
281 // tv.tv_usec = (msecs % 1000) * 1000;
286 // ret = select(m_socketDescriptor + 1, &fds, 0, 0, (msecs < 0 ? 0 : &tv));
288 // ret = select(m_socketDescriptor + 1, 0, &fds, 0, (msecs < 0 ? 0 : &tv));
292 int64_t TcpSocketEngine::nativeWrite(const char* data, size_t length) {
294 // ssize_t writtenBytes = write(m_socketDescriptor, data, length);
295 // if ( writtenBytes < 0 ) {
299 // writtenBytes = -1;
300 // m_socketError = TcpSocket::RemoteHostClosedError;
301 // m_errorString = "remote host closed connection";
312 // return static_cast<int64_t>(writtenBytes);