]> git.donarmstrong.com Git - bamtools.git/commitdiff
Fixed: premature EOF issues & updated Windows implementation
authorderek <derekwbarnett@gmail.com>
Thu, 8 Dec 2011 07:59:37 +0000 (02:59 -0500)
committerderek <derekwbarnett@gmail.com>
Thu, 8 Dec 2011 07:59:37 +0000 (02:59 -0500)
src/api/CMakeLists.txt
src/api/internal/io/BamFtp_p.cpp
src/api/internal/io/BamHttp_p.cpp
src/api/internal/io/HostAddress_p.cpp
src/api/internal/io/HostInfo_p.cpp
src/api/internal/io/NetWin_p.h
src/api/internal/io/RollingBuffer_p.cpp
src/api/internal/io/TcpSocketEngine_p.cpp
src/api/internal/io/TcpSocketEngine_p.h
src/api/internal/io/TcpSocketEngine_win_p.cpp
src/api/internal/io/TcpSocket_p.cpp

index cdfc10bdd634c1d5cce1500baf0ed01c07795b58..1af7a7f917a34077699408ab574586ab5a12c7ea 100644 (file)
@@ -43,7 +43,7 @@ set_target_properties( BamTools-static PROPERTIES
                        OUTPUT_NAME "bamtools" 
                        PREFIX "lib" )
 
-# link libraries with zlib automatically
+# link libraries automatically with zlib (and Winsock2, if applicable)
 if( _WIN32 )
     set( APILibs z ws2_32 )
 else( _WIN32 )
index a90a35743a91507ece1ed17078b5d2e7e7195cdb..b8514016d305e5f69e6fd3f16c1ff744654fdf73 100644 (file)
@@ -2,7 +2,7 @@
 // BamFtp_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides reading/writing of BAM files on FTP server
 // ***************************************************************************
@@ -78,7 +78,7 @@ static inline
 string toLower(const string& s) {
     string out;
     const size_t sSize = s.size();
-    out.reserve(sSize);
+    out.resize(sSize);
     for ( size_t i = 0; i < sSize; ++i )
         out[i] = tolower(s[i]);
     return out;
@@ -136,7 +136,7 @@ bool BamFtp::ConnectCommandSocket(void) {
 
     // connect to FTP server
     if ( !m_commandSocket->ConnectToHost(m_hostname, m_port, m_mode) ) {
-        SetErrorString("BamFtp::ConnectCommandSocket", "could not connect to host");
+        SetErrorString("BamFtp::ConnectCommandSocket", "could not connect to host - ");
         return false;
     }
 
@@ -180,7 +180,7 @@ bool BamFtp::ConnectDataSocket(void) {
     }
 
     // make sure we're starting with a fresh data channel
-    if ( m_dataSocket->IsConnected() ) 
+    if ( m_dataSocket->IsConnected() )
         m_dataSocket->DisconnectFromHost();
 
     // send passive connection command
@@ -227,7 +227,7 @@ bool BamFtp::ConnectDataSocket(void) {
         m_dataSocket->DisconnectFromHost();
         return false;
     }
-    
+
     // make sure we have reply code 150 (all good)
     if ( !startsWith(m_response, "150") ) {
         // TODO: set error string
@@ -368,21 +368,11 @@ int64_t BamFtp::Read(char* data, const unsigned int numBytes) {
 }
 
 int64_t BamFtp::ReadCommandSocket(char* data, const unsigned int maxNumBytes) {
-
-    // try to read 'remainingBytes' from socket
-    const int64_t numBytesRead = m_commandSocket->Read(data, maxNumBytes);
-    if ( numBytesRead < 0 )
-        return -1;
-    return numBytesRead;
+    return m_commandSocket->Read(data, maxNumBytes);
 }
 
 int64_t BamFtp::ReadDataSocket(char* data, const unsigned int maxNumBytes) {
-
-    // try to read 'remainingBytes' from socket
-    const int64_t numBytesRead = m_dataSocket->Read(data, maxNumBytes);
-    if ( numBytesRead < 0 )
-        return -1;
-    return numBytesRead;
+    return m_dataSocket->Read(data, maxNumBytes);
 }
 
 bool BamFtp::ReceiveReply(void) {
index ba573372b9f45265a34a4b7ba5a0963491804834..377be820e7e2a3ffb29032b7c18486e18041f8e5 100644 (file)
@@ -275,12 +275,7 @@ int64_t BamHttp::Read(char* data, const unsigned int numBytes) {
 }
 
 int64_t BamHttp::ReadFromSocket(char* data, const unsigned int maxNumBytes) {
-
-    // try to read 'remainingBytes' from socket
-    const int64_t numBytesRead = m_socket->Read(data, maxNumBytes);
-    if ( numBytesRead < 0 )
-        return -1;
-    return numBytesRead;
+    return m_socket->Read(data, maxNumBytes);
 }
 
 bool BamHttp::ReceiveResponse(void) {
index 873087b07fea1b94a81facb1ca7751a3ea1a0eb4..5c42c5b352a80b482d66efbd75662da24f221c2d 100644 (file)
@@ -2,7 +2,7 @@
 // HostAddress_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides a generic IP address container
 // ***************************************************************************
index 80343f1cd9d1495486ebbe56fa9c9d32f6632073..40b1047214233b37c59a72cf6625ca83fb36318e 100644 (file)
@@ -2,7 +2,7 @@
 // HostInfo_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides DNS lookup functionality for hostname & its discovered addresses
 // ***************************************************************************
@@ -81,6 +81,7 @@ void HostInfo::SetHostName(const string& name) {
 HostInfo HostInfo::Lookup(const string& hostname, const string& port) {
 
     HostInfo result;
+    result.SetHostName(hostname);
     set<HostAddress> uniqueAddresses;
 
 #ifdef _WIN32
index bcef955b9a7bb003f4fc568d7eb09cea050ba5a9..3796e01e761a27d80771f850163476b10751db13 100644 (file)
@@ -2,11 +2,11 @@
 // NetWin_p.h (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides common networking-related includes, etc. for Windows systems
 //
-// Note: only supports XP and later
+// Note: requires Windows XP or later
 // ***************************************************************************
 
 #ifndef NETWIN_P_H
@@ -38,7 +38,7 @@
 namespace BamTools {
 namespace Internal {
 
-// use RAII to ensure WSA is en
+// use RAII to ensure WSA is initialized
 class WindowsSockInit {
     public:
         WindowsSockInit(void) {
index c3f709d6fdf5ad1a13ac998b80ef95bdac7da95b..10e762732d201f2351182df9b189378f591bc7a5 100644 (file)
@@ -2,7 +2,7 @@
 // RollingBuffer_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides a dynamic I/O FIFO byte queue, which removes bytes as they are
 // read from the front of the buffer and grows to accept bytes being written
@@ -167,6 +167,10 @@ void RollingBuffer::Free(size_t n) {
 
 size_t RollingBuffer::IndexOf(char c) const {
 
+    // skip processing if empty buffer
+    if ( IsEmpty() )
+        return string::npos;
+
     size_t index(0);
 
     // iterate over byte arrays
index 467eaeb83921194a3d077a43b5bb879e1e521d41..65587b286218a88bdbbd943a84e81c548eb23ea4 100644 (file)
@@ -2,7 +2,7 @@
 // TcpSocketEngine_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides low-level implementation of TCP I/O
 // ***************************************************************************
@@ -13,6 +13,7 @@
 
 #include "api/internal/io/HostInfo_p.h"
 #include "api/internal/io/TcpSocketEngine_p.h"
+
 using namespace BamTools;
 using namespace BamTools::Internal;
 
@@ -150,7 +151,7 @@ bool TcpSocketEngine::WaitForRead(int msec, bool* timedOut) {
     *timedOut = false;
 
     // need to wait for our socket to be ready to read
-    int ret = nativeSelect(msec, true);
+    const int ret = nativeSelect(msec, true);
 
     // if timed out
     if ( ret == 0 ) {
@@ -169,7 +170,7 @@ bool TcpSocketEngine::WaitForWrite(int msec, bool* timedOut) {
     *timedOut = false;
 
     // need to wait for our socket to be ready to write
-    int ret = nativeSelect(msec, false);
+    const int ret = nativeSelect(msec, false);
 
     // if timed out
     if ( ret == 0 ) {
index 1a1a944a70b61f0ea5d1a1e774634c42a3a17363..9218278b6342de7675528a4fdab0ddc773af9c03 100644 (file)
@@ -2,7 +2,7 @@
 // TcpSocketEngine_p.h (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides low-level implementation of TCP I/O
 // ***************************************************************************
 #include "api/internal/io/HostAddress_p.h"
 #include "api/internal/io/TcpSocket_p.h"
 
+#ifdef _WIN32
+#  include "api/internal/io/NetWin_p.h"
+#endif
+
 namespace BamTools {
 namespace Internal {
 
@@ -87,6 +91,10 @@ struct TcpSocketEngine {
         TcpSocket::SocketError m_socketError;
         TcpSocket::SocketState m_socketState;
         std::string m_errorString;
+
+#ifdef _WIN32
+        WindowsSockInit m_win;
+#endif
 };
 
 } // namespace Internal
index d1691aca72dd874585680e099c6c5272b2e69c76..c4d9b47d700361b8974ac20fa36133012caaa692 100644 (file)
@@ -2,7 +2,7 @@
 // TcpSocketEngine_win_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 15 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides low-level implementation of TCP I/O for all Windows systems
 // ***************************************************************************
@@ -14,19 +14,9 @@ using namespace BamTools::Internal;
 
 #include <cstring>
 #include <iostream>
+#include <sstream>
 using namespace std;
 
-// ------------------------
-// static utility methods
-// ------------------------
-
-namespace BamTools {
-namespace Internal {
-
-
-} // namespace Internal
-} // namespace BamTools
-
 // --------------------------------
 // TcpSocketEngine implementation
 // --------------------------------
@@ -162,6 +152,10 @@ bool TcpSocketEngine::nativeCreateSocket(HostAddress::NetworkProtocol protocol)
                 m_errorString = "out of resources";
                 break;
             default:
+                m_socketError = TcpSocket::UnknownSocketError;
+                stringstream errStream("");
+                errStream << "WSA ErrorCode: " << errorCode;
+                m_errorString = errStream.str();
                 break;
         }
 
@@ -203,23 +197,10 @@ int64_t TcpSocketEngine::nativeRead(char* dest, size_t max) {
     DWORD flags = 0;
     DWORD bytesRead = 0;
     const int readResult = WSARecv(m_socketDescriptor, &buf, 1, &bytesRead, &flags, 0, 0);
+    if ( readResult == SOCKET_ERROR )
+        return -1;
 
-    // if error encountered
-    if ( readResult == SOCKET_ERROR ) {
-        const int errorCode = WSAGetLastError();
-        switch ( errorCode ) {
-            case WSAEWOULDBLOCK: // nothing read this time, but more coming later
-                return -2;
-            default:
-                return -1;        // on any other errors
-        }
-    }
-
-    //  check if nothing was read this time, but more is coming
-    if ( WSAGetLastError() == WSAEWOULDBLOCK )
-        return -2;
-
-    // otherwise return number of bytes read
+    // return number of bytes read
     return static_cast<int64_t>(bytesRead);
 }
 
@@ -252,24 +233,9 @@ int64_t TcpSocketEngine::nativeWrite(const char* data, size_t length) {
     DWORD flags = 0;
     DWORD bytesWritten = 0;
     const int writeResult = WSASend(m_socketDescriptor, &buf, 1, &bytesWritten, flags, 0, 0);
+    if ( writeResult == SOCKET_ERROR )
+        return -1;
 
-    // error encountered
-    if ( writeResult == SOCKET_ERROR )  {
-
-        const int errorCode = WSAGetLastError();
-        switch ( errorCode ) {
-            case WSAEWOULDBLOCK:
-                return 0;
-            case WSAECONNRESET:
-            case WSAECONNABORTED:
-                m_socketError = TcpSocket::NetworkError;
-                m_errorString = "connection reset or aborted";
-                return -1;
-            default:
-                return -1;
-        }
-    }
-
-    // otherwise return number of bytes written
+    // return number of bytes written
     return static_cast<int64_t>(bytesWritten);
 }
index b27635ea5de3a41fb07c6006378566037f125617..619571051b2eb2707d591d63c0b2f83fc7f522c4 100644 (file)
@@ -2,7 +2,7 @@
 // TcpSocket_p.cpp (c) 2011 Derek Barnett
 // Marth Lab, Department of Biology, Boston College
 // ---------------------------------------------------------------------------
-// Last modified: 7 December 2011 (DB)
+// Last modified: 8 December 2011 (DB)
 // ---------------------------------------------------------------------------
 // Provides basic TCP I/O interface
 // ***************************************************************************
@@ -69,14 +69,14 @@ bool TcpSocket::ConnectImpl(const HostInfo& hostInfo,
 {
     // skip if we're already connected
     if ( m_state == TcpSocket::ConnectedState ) {
-        m_error = TcpSocket::SocketResourceError; 
+        m_error = TcpSocket::SocketResourceError;
         m_errorString = "socket already connected";
         return false;
     }
 
     // reset socket state
     m_hostName   = hostInfo.HostName();
-    m_mode       = mode;    
+    m_mode       = mode;
     m_state      = TcpSocket::UnconnectedState;
     m_error      = TcpSocket::UnknownSocketError;
 //    m_localPort  = 0;
@@ -154,7 +154,7 @@ bool TcpSocket::ConnectToHost(const string& hostName,
     // if host name was IP address ("x.x.x.x" or IPv6 format)
     // otherwise host name was 'plain-text' ("www.foo.bar")
     // we need to look up IP address(es)
-    if ( hostAddress.HasIPAddress() ) 
+    if ( hostAddress.HasIPAddress() )
         info.SetAddresses( vector<HostAddress>(1, hostAddress) );
     else
         info = HostInfo::Lookup(hostName, port);
@@ -275,24 +275,25 @@ int64_t TcpSocket::ReadFromSocket(void) {
 
         // if we simply timed out
         if ( timedOut ) {
+            // TODO: get add'l error info from engine ?
             m_errorString = "TcpSocket::ReadFromSocket - timed out waiting for ready read";
-            // get error from engine ?
-            return -1;
         }
 
-        // otherwise, there was an error
+        // otherwise, there was some other error
         else {
+            // TODO: get add'l error info from engine ?
             m_errorString = "TcpSocket::ReadFromSocket - encountered error while waiting for ready read";
-            // get error from engine ?
-            return -1;
         }
+
+        // return failure
+        return -1;
     }
 
     // get number of bytes available from socket
     const int64_t bytesToRead = m_engine->NumBytesAvailable();
     if ( bytesToRead < 0 ) {
+        // TODO: get add'l error info from engine ?
         m_errorString = "TcpSocket::ReadFromSocket - encountered error while determining numBytesAvailable";
-        // get error from engine ?
         return -1;
     }
 
@@ -300,8 +301,8 @@ int64_t TcpSocket::ReadFromSocket(void) {
     char* buffer = m_readBuffer.Reserve(bytesToRead);
     const int64_t numBytesRead = m_engine->Read(buffer, bytesToRead);
     if ( numBytesRead == -1 ) {
+        // TODO: get add'l error info from engine ?
         m_errorString = "TcpSocket::ReadFromSocket - encountered error while reading bytes";
-        // get error from engine ?
     }
 
     // return number of bytes actually read
@@ -327,7 +328,7 @@ string TcpSocket::ReadLine(int64_t max) {
 
         int64_t readResult;
         do {
-            result.Resize( static_cast<size_t>(std::min(bufferMax, result.Size() + DEFAULT_BUFFER_SIZE)) );
+            result.Resize( static_cast<size_t>(min(bufferMax, result.Size() + DEFAULT_BUFFER_SIZE)) );
             readResult = ReadLine(result.Data()+readBytes, result.Size()-readBytes);
             if ( readResult > 0 || readBytes == 0 )
                 readBytes += readResult;
@@ -347,13 +348,13 @@ string TcpSocket::ReadLine(int64_t max) {
 }
 
 int64_t TcpSocket::ReadLine(char* dest, size_t max) {
-    
+
     // wait for buffer to contain line contents
     if ( !WaitForReadLine() ) {
         m_errorString = "TcpSocket::ReadLine - error waiting for read line";
         return -1;
     }
-    
+
     // leave room for null term
     if ( max < 2 )
         return -1;
@@ -393,11 +394,11 @@ bool TcpSocket::WaitForReadLine(void) {
 
     // wait until we can read a line (will return immediately if already capable)
     while ( !CanReadLine() ) {
-        if ( !ReadFromSocket() ) 
+        if ( !ReadFromSocket() )
             return false;
     }
 
-    // if we get here, success  
+    // if we get here, success
     return true;
 }
 
@@ -406,22 +407,23 @@ int64_t TcpSocket::Write(const char* data, const unsigned int numBytes) {
     // single-shot attempt at write (not buffered, just try to shove the data through socket)
     // this method purely exists to send 'small' HTTP requests/FTP commands from client to server
 
-    int64_t bytesWritten(0);
-
     // wait for our socket to be write-able
     bool timedOut;
     const bool isReadyWrite = m_engine->WaitForWrite(3000, &timedOut);
+
+    // if ready, return number of bytes written
     if ( isReadyWrite )
-        bytesWritten = m_engine->Write(data, numBytes);
+        return m_engine->Write(data, numBytes);
+
+    // otherwise, socket not ready for writing
+    // set error string depending on reason & return failure
+    if ( !timedOut ) {
+        // TODO: get add'l error info from engine ??
+        m_errorString = "TcpSocket::Write - timed out waiting for ready-write";
+    }
     else {
-        // timeout is OK (with current setup), we'll just return 0 & try again
-        // but we need to report if engine encountered some other error
-        if ( !timedOut ) {
-            // TODO: set error string
-            bytesWritten = -1;
-        }
+        // TODO: get add'l error info from engine ??
+        m_errorString = "TcpSocket::Write - error encountered while waiting for ready-write";
     }
-
-    // return actual number of bytes written to socket
-    return bytesWritten;
+    return -1;
 }