]> git.donarmstrong.com Git - bamtools.git/blobdiff - src/api/internal/io/TcpSocketEngine_p.cpp
Implemented basic TCP support layer
[bamtools.git] / src / api / internal / io / TcpSocketEngine_p.cpp
diff --git a/src/api/internal/io/TcpSocketEngine_p.cpp b/src/api/internal/io/TcpSocketEngine_p.cpp
new file mode 100644 (file)
index 0000000..d13b0bc
--- /dev/null
@@ -0,0 +1,183 @@
+#include "api/internal/io/HostInfo_p.h"
+#include "api/internal/io/TcpSocketEngine_p.h"
+
+using namespace BamTools;
+using namespace BamTools::Internal;
+
+TcpSocketEngine::TcpSocketEngine(void)
+    : m_socketDescriptor(-1)
+//    , m_localPort(0)
+    , m_remotePort(0)
+    , m_socketError(TcpSocket::UnknownSocketError)
+    , m_socketState(TcpSocket::UnconnectedState)
+{ }
+
+TcpSocketEngine::TcpSocketEngine(const TcpSocketEngine& other)
+    : m_socketDescriptor(other.m_socketDescriptor)
+//    , m_localAddress(other.m_localAddress)
+    , m_remoteAddress(other.m_remoteAddress)
+//    , m_localPort(other.m_localPort)
+    , m_remotePort(other.m_remotePort)
+    , m_socketError(other.m_socketError)
+    , m_socketState(other.m_socketState)
+    , m_errorString(other.m_errorString)
+{ }
+
+TcpSocketEngine::~TcpSocketEngine(void) {
+    Close();
+}
+
+void TcpSocketEngine::Close(void) {
+
+    // close socket if we have valid FD
+    if ( m_socketDescriptor != -1 ) {
+        nativeClose();
+        m_socketDescriptor = -1;
+    }
+
+    // reset state
+    m_socketState = TcpSocket::UnconnectedState;
+//    m_localAddress.Clear();
+    m_remoteAddress.Clear();
+//    m_localPort = 0;
+    m_remotePort = 0;
+}
+
+bool TcpSocketEngine::Connect(const HostAddress& address, const uint16_t port) {
+
+    // return failure if invalid FD or already connected
+    if ( !IsValid() || (m_socketState == TcpSocket::ConnectedState) ) {
+        // TODO: set error string
+        return false;
+    }
+
+    // attempt to connect to host address on requested port
+    if ( !nativeConnect(address, port) ) {
+        // TODO: set error string
+        return false;
+    }
+
+    // if successful, store remote host address port & return success
+    // TODO: (later) fetch proxied remote & local host/port  here
+    m_remoteAddress = address;
+    m_remotePort    = port;
+    return true;
+}
+
+std::string TcpSocketEngine::GetErrorString(void) const {
+    return m_errorString;
+}
+
+//HostAddress TcpSocketEngine::GetLocalAddress(void) const {
+//    return m_localAddress;
+//}
+
+//uint16_t TcpSocketEngine::GetLocalPort(void) const {
+//    return m_localPort;
+//}
+
+HostAddress TcpSocketEngine::GetRemoteAddress(void) const {
+    return m_remoteAddress;
+}
+
+uint16_t TcpSocketEngine::GetRemotePort(void) const {
+    return m_remotePort;
+}
+
+int TcpSocketEngine::GetSocketDescriptor(void) const {
+    return m_socketDescriptor;
+}
+
+TcpSocket::SocketError TcpSocketEngine::GetSocketError(void) {
+    return m_socketError;
+}
+
+TcpSocket::SocketState TcpSocketEngine::GetSocketState(void) {
+    return m_socketState;
+}
+
+bool TcpSocketEngine::Initialize(HostAddress::NetworkProtocol protocol) {
+
+    // close current socket if we have one open
+    if ( IsValid() )
+        Close();
+
+    // attempt to create new socket
+    return nativeCreateSocket(protocol);
+}
+
+bool TcpSocketEngine::IsValid(void) const {
+    return (m_socketDescriptor != -1);
+}
+
+int64_t TcpSocketEngine::NumBytesAvailable(void) const {
+
+    // return 0 if socket FD is invalid
+    if ( !IsValid() ) {
+        // TODO: set error string
+        return -1;
+    }
+
+    // otherwise check socket to see how much is ready
+    return nativeNumBytesAvailable();
+}
+
+int64_t TcpSocketEngine::Read(char* dest, size_t max) {
+
+    // return failure if can't read
+    if ( !IsValid() || (m_socketState != TcpSocket::ConnectedState) )
+        return -1;
+
+    // otherwise return number of bytes read
+    return nativeRead(dest, max);
+}
+
+bool TcpSocketEngine::WaitForRead(int msec, bool* timedOut) {
+
+    // reset timedOut flag
+    *timedOut = false;
+
+    // need to wait for our socket to be ready to read
+    int ret = nativeSelect(msec, true);
+
+    // if timed out
+    if ( ret == 0 ) {
+        *timedOut = true;
+        m_socketError = TcpSocket::SocketTimeoutError;
+        m_errorString = "socket timed out";
+    }
+
+    // return if any sockets available for reading
+    return ( ret > 0 );
+}
+
+bool TcpSocketEngine::WaitForWrite(int msec, bool* timedOut) {
+
+    // reset timedOut flag
+    *timedOut = false;
+
+    // need to wait for our socket to be ready to write
+    int ret = nativeSelect(msec, false);
+
+    // if timed out
+    if ( ret == 0 ) {
+        *timedOut = true;
+        m_socketError = TcpSocket::SocketTimeoutError;
+        m_errorString = "socket timed out";
+    }
+
+    // return if any sockets available for reading
+    return ( ret > 0 );
+}
+
+int64_t TcpSocketEngine::Write(const char* data, size_t length) {
+
+    // return failure if can't write
+    if ( !IsValid() || (m_socketState != TcpSocket::ConnectedState) ) {
+        // TODO: set error string
+        return -1;
+    }
+
+    // otherwise return number of bytes written
+    return nativeWrite(data, length);
+}