From e4cb7afa9b8774b4db39db1c60607460676419d3 Mon Sep 17 00:00:00 2001 From: derek Date: Thu, 10 Nov 2011 13:39:14 -0500 Subject: [PATCH] Updated file headers (filename, license, description, etc) --- src/api/IBamIODevice.h | 2 +- src/api/internal/index/BamIndexFactory_p.cpp | 13 +- src/api/internal/index/BamStandardIndex_p.cpp | 2 +- src/api/internal/index/BamStandardIndex_p.h | 2 +- src/api/internal/index/BamToolsIndex_p.cpp | 50 +- src/api/internal/index/BamToolsIndex_p.h | 3 +- src/api/internal/io/BamFile_p.cpp | 2 +- src/api/internal/io/BamFile_p.h | 2 +- src/api/internal/io/BamFtp_p.cpp | 58 +- src/api/internal/io/BamFtp_p.h | 5 +- src/api/internal/io/BamHttp_p.cpp | 35 +- src/api/internal/io/BamHttp_p.h | 2 +- src/api/internal/io/BamPipe_p.cpp | 6 +- src/api/internal/io/BamPipe_p.h | 2 +- src/api/internal/io/ByteArray_p.cpp | 11 +- src/api/internal/io/ByteArray_p.h | 19 + src/api/internal/io/HostAddress_p.cpp | 35 +- src/api/internal/io/HostAddress_p.h | 19 + src/api/internal/io/HostInfo_p.cpp | 16 +- src/api/internal/io/HostInfo_p.h | 19 + src/api/internal/io/HttpHeader_p.cpp | 10 + src/api/internal/io/HttpHeader_p.h | 20 + src/api/internal/io/NetUnix_p.h | 25 +- src/api/internal/io/NetWin_p.h | 21 + src/api/internal/io/RollingBuffer_p.cpp | 51 +- src/api/internal/io/RollingBuffer_p.h | 56 +- src/api/internal/io/TcpSocketEngine_p.cpp | 14 +- src/api/internal/io/TcpSocketEngine_p.h | 22 +- .../internal/io/TcpSocketEngine_unix_p.cpp | 16 +- src/api/internal/io/TcpSocketEngine_win_p.cpp | 512 +++++++++--------- src/api/internal/io/TcpSocket_p.cpp | 6 +- src/api/internal/io/TcpSocket_p.h | 4 +- 32 files changed, 615 insertions(+), 445 deletions(-) diff --git a/src/api/IBamIODevice.h b/src/api/IBamIODevice.h index 8a74696..cf64129 100644 --- a/src/api/IBamIODevice.h +++ b/src/api/IBamIODevice.h @@ -2,7 +2,7 @@ // IBamIODevice.h (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 10 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Base class for all BAM I/O devices (e.g. local file, pipe, HTTP, FTP, etc.) // diff --git a/src/api/internal/index/BamIndexFactory_p.cpp b/src/api/internal/index/BamIndexFactory_p.cpp index c5399b2..ab7751f 100644 --- a/src/api/internal/index/BamIndexFactory_p.cpp +++ b/src/api/internal/index/BamIndexFactory_p.cpp @@ -2,12 +2,11 @@ // BamIndexFactory_p.cpp (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides interface for generating BamIndex implementations // *************************************************************************** -#include "api/BamAux.h" #include "api/internal/index/BamIndexFactory_p.h" #include "api/internal/index/BamStandardIndex_p.h" #include "api/internal/index/BamToolsIndex_p.h" @@ -31,10 +30,6 @@ const string BamIndexFactory::CreateIndexFilename(const string& bamFilename, // creates a new BamIndex object, depending on extension of @indexFilename BamIndex* BamIndexFactory::CreateIndexFromFilename(const string& indexFilename, BamReaderPrivate* reader) { -// // if file doesn't exist, return null index -// if ( !BamTools::FileExists(indexFilename) ) -// return 0; - // get file extension from index filename, including dot (".EXT") // if can't get file extension, return null index const string extension = FileExtension(indexFilename); @@ -91,19 +86,19 @@ const string BamIndexFactory::FindIndexFilename(const string& bamFilename, // try to find index of preferred type first // return index filename if found string indexFilename = CreateIndexFilename(bamFilename, preferredType); - if ( !indexFilename.empty() /*&& BamTools::FileExists(indexFilename)*/ ) + if ( !indexFilename.empty() ) return indexFilename; // couldn't find preferred type, try the other supported types // return index filename if found if ( preferredType != BamIndex::STANDARD ) { indexFilename = CreateIndexFilename(bamFilename, BamIndex::STANDARD); - if ( !indexFilename.empty() /*&& BamTools::FileExists(indexFilename)*/ ) + if ( !indexFilename.empty() ) return indexFilename; } if ( preferredType != BamIndex::BAMTOOLS ) { indexFilename = CreateIndexFilename(bamFilename, BamIndex::BAMTOOLS); - if ( !indexFilename.empty()/* && BamTools::FileExists(indexFilename) */) + if ( !indexFilename.empty() ) return indexFilename; } diff --git a/src/api/internal/index/BamStandardIndex_p.cpp b/src/api/internal/index/BamStandardIndex_p.cpp index 56c92f9..dcdec8d 100644 --- a/src/api/internal/index/BamStandardIndex_p.cpp +++ b/src/api/internal/index/BamStandardIndex_p.cpp @@ -2,7 +2,7 @@ // BamStandardIndex.cpp (c) 2010 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides index operations for the standardized BAM index format (".bai") // *************************************************************************** diff --git a/src/api/internal/index/BamStandardIndex_p.h b/src/api/internal/index/BamStandardIndex_p.h index dfa81ee..8322e5f 100644 --- a/src/api/internal/index/BamStandardIndex_p.h +++ b/src/api/internal/index/BamStandardIndex_p.h @@ -2,7 +2,7 @@ // BamStandardIndex.h (c) 2010 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 10 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides index operations for the standardized BAM index format (".bai") // *************************************************************************** diff --git a/src/api/internal/index/BamToolsIndex_p.cpp b/src/api/internal/index/BamToolsIndex_p.cpp index 2d05eaa..bb09bc9 100644 --- a/src/api/internal/index/BamToolsIndex_p.cpp +++ b/src/api/internal/index/BamToolsIndex_p.cpp @@ -2,7 +2,7 @@ // BamToolsIndex.cpp (c) 2010 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides index operations for the BamTools index format (".bti") // *************************************************************************** @@ -39,16 +39,10 @@ const int BamToolsIndex::SIZEOF_BLOCK = sizeof(int32_t)*2 + sizeof(int64 // ---------------------------- BamToolsIndex::RaiiWrapper::RaiiWrapper(void) - : IndexStream(0) - , Device(0) + : Device(0) { } BamToolsIndex::RaiiWrapper::~RaiiWrapper(void) { - if ( IndexStream ) { - fclose(IndexStream); - IndexStream = 0; - } - if ( Device ) { Device->Close(); delete Device; @@ -93,8 +87,6 @@ void BamToolsIndex::CheckVersion(void) { // read version from file const int64_t numBytesRead = m_resources.Device->Read((char*)&m_inputVersion, sizeof(m_inputVersion)); -// size_t elementsRead = fread(&m_inputVersion, sizeof(m_inputVersion), 1, m_resources.IndexStream); -// if ( elementsRead != 1 ) if ( numBytesRead != sizeof(m_inputVersion) ) throw BamException("BamToolsIndex::CheckVersion", "could not read format version"); if ( m_isBigEndian ) SwapEndian_32(m_inputVersion); @@ -131,9 +123,6 @@ void BamToolsIndex::ClearReferenceEntry(BtiReferenceEntry& refEntry) { void BamToolsIndex::CloseFile(void) { if ( IsDeviceOpen() ) { - fclose(m_resources.IndexStream); - m_resources.IndexStream = 0; - m_resources.Device->Close(); delete m_resources.Device; m_resources.Device = 0; @@ -375,7 +364,6 @@ bool BamToolsIndex::IsDeviceOpen(void) const { if ( m_resources.Device == 0 ) return false; return m_resources.Device->IsOpen(); -// return ( m_resources.IndexStream != 0 ); } // attempts to use index data to jump to @region, returns success/fail @@ -458,27 +446,21 @@ void BamToolsIndex::LoadHeader(void) { // use file's BTI block size to set member variable const int64_t numBytesRead = m_resources.Device->Read((char*)&m_blockSize, sizeof(m_blockSize)); -// const size_t elementsRead = fread(&m_blockSize, sizeof(m_blockSize), 1, m_resources.IndexStream); if ( m_isBigEndian ) SwapEndian_32(m_blockSize); -// if ( elementsRead != 1 ) if ( numBytesRead != sizeof(m_blockSize) ) throw BamException("BamToolsIndex::LoadHeader", "could not read BTI block size"); } void BamToolsIndex::LoadNumBlocks(int& numBlocks) { const int64_t numBytesRead = m_resources.Device->Read((char*)&numBlocks, sizeof(numBlocks)); -// const size_t elementsRead = fread(&numBlocks, sizeof(numBlocks), 1, m_resources.IndexStream); if ( m_isBigEndian ) SwapEndian_32(numBlocks); -// if ( elementsRead != 1 ) if ( numBytesRead != sizeof(numBlocks) ) throw BamException("BamToolsIndex::LoadNumBlocks", "could not read number of BTI blocks"); } void BamToolsIndex::LoadNumReferences(int& numReferences) { const int64_t numBytesRead = m_resources.Device->Read((char*)&numReferences, sizeof(numReferences)); -// const size_t elementsRead = fread(&numReferences, sizeof(numReferences), 1, m_resources.IndexStream); if ( m_isBigEndian ) SwapEndian_32(numReferences); -// if ( elementsRead != 1 ) if ( numBytesRead != sizeof(numReferences) ) throw BamException("BamToolsIndex::LoadNumReferences", "could not read number of references"); } @@ -509,7 +491,6 @@ void BamToolsIndex::OpenFile(const std::string& filename, IBamIODevice::OpenMode } // attempt to open file -// m_resources.IndexStream = fopen(filename.c_str(), mode); m_resources.Device->Open(mode); if ( !IsDeviceOpen() ) { const string message = string("could not open file: ") + filename; @@ -520,11 +501,6 @@ void BamToolsIndex::OpenFile(const std::string& filename, IBamIODevice::OpenMode void BamToolsIndex::ReadBlock(BtiBlock& block) { // read in block data members -// size_t elementsRead = 0; -// elementsRead += fread(&block.MaxEndPosition, sizeof(block.MaxEndPosition), 1, m_resources.IndexStream); -// elementsRead += fread(&block.StartOffset, sizeof(block.StartOffset), 1, m_resources.IndexStream); -// elementsRead += fread(&block.StartPosition, sizeof(block.StartPosition), 1, m_resources.IndexStream); - int64_t numBytesRead = 0; numBytesRead += m_resources.Device->Read((char*)&block.MaxEndPosition, sizeof(block.MaxEndPosition)); numBytesRead += m_resources.Device->Read((char*)&block.StartOffset, sizeof(block.StartOffset)); @@ -537,7 +513,7 @@ void BamToolsIndex::ReadBlock(BtiBlock& block) { SwapEndian_32(block.StartPosition); } -// if ( elementsRead != 3 ) + // check block read ok const int expectedBytes = sizeof(block.MaxEndPosition) + sizeof(block.StartOffset) + sizeof(block.StartPosition); @@ -575,7 +551,6 @@ void BamToolsIndex::ReadReferenceEntry(BtiReferenceEntry& refEntry) { void BamToolsIndex::Seek(const int64_t& position, const int origin) { if ( !m_resources.Device->Seek(position, origin) ) -// if ( fseek64(m_resources.IndexStream, position, origin) != 0 ) throw BamException("BamToolsIndex::Seek", "could not seek in BAI file"); } @@ -585,7 +560,6 @@ void BamToolsIndex::SkipBlocks(const int& numBlocks) { int64_t BamToolsIndex::Tell(void) const { return m_resources.Device->Tell(); -// return ftell64(m_resources.IndexStream); } void BamToolsIndex::WriteBlock(const BtiBlock& block) { @@ -607,15 +581,11 @@ void BamToolsIndex::WriteBlock(const BtiBlock& block) { numBytesWritten += m_resources.Device->Write((const char*)&maxEndPosition, sizeof(maxEndPosition)); numBytesWritten += m_resources.Device->Write((const char*)&startOffset, sizeof(startOffset)); numBytesWritten += m_resources.Device->Write((const char*)&startPosition, sizeof(startPosition)); + + // check block written ok const int expectedBytes = sizeof(maxEndPosition) + sizeof(startOffset) + sizeof(startPosition); - -// size_t elementsWritten = 0; -// elementsWritten += fwrite(&maxEndPosition, sizeof(maxEndPosition), 1, m_resources.IndexStream); -// elementsWritten += fwrite(&startOffset, sizeof(startOffset), 1, m_resources.IndexStream); -// elementsWritten += fwrite(&startPosition, sizeof(startPosition), 1, m_resources.IndexStream); -// if ( elementsWritten != 3 ) if ( numBytesWritten != expectedBytes ) throw BamException("BamToolsIndex::WriteBlock", "could not write BTI block"); } @@ -630,36 +600,30 @@ void BamToolsIndex::WriteBlocks(const BtiBlockVector& blocks) { void BamToolsIndex::WriteHeader(void) { int64_t numBytesWritten = 0 ; -// size_t elementsWritten = 0; // write BTI index format 'magic number' numBytesWritten += m_resources.Device->Write(BamToolsIndex::BTI_MAGIC, 4); -// elementsWritten += fwrite(BamToolsIndex::BTI_MAGIC, 1, 4, m_resources.IndexStream); // write BTI index format version int32_t currentVersion = (int32_t)m_outputVersion; if ( m_isBigEndian ) SwapEndian_32(currentVersion); numBytesWritten += m_resources.Device->Write((const char*)¤tVersion, sizeof(currentVersion)); -// elementsWritten += fwrite(¤tVersion, sizeof(currentVersion), 1, m_resources.IndexStream); // write block size uint32_t blockSize = m_blockSize; if ( m_isBigEndian ) SwapEndian_32(blockSize); numBytesWritten += m_resources.Device->Write((const char*)&blockSize, sizeof(blockSize)); -// elementsWritten += fwrite(&blockSize, sizeof(blockSize), 1, m_resources.IndexStream); // write number of references int32_t numReferences = m_indexFileSummary.size(); if ( m_isBigEndian ) SwapEndian_32(numReferences); numBytesWritten += m_resources.Device->Write((const char*)&numReferences, sizeof(numReferences)); -// elementsWritten += fwrite(&numReferences, sizeof(numReferences), 1, m_resources.IndexStream); + // check header written ok const int expectedBytes = 4 + sizeof(currentVersion) + sizeof(blockSize) + sizeof(numReferences); - -// if ( elementsWritten != 7 ) if ( numBytesWritten != expectedBytes ) throw BamException("BamToolsIndex::WriteHeader", "could not write BTI header"); } @@ -670,8 +634,6 @@ void BamToolsIndex::WriteReferenceEntry(const BtiReferenceEntry& refEntry) { uint32_t numBlocks = refEntry.Blocks.size(); if ( m_isBigEndian ) SwapEndian_32(numBlocks); const int64_t numBytesWritten = m_resources.Device->Write((const char*)&numBlocks, sizeof(numBlocks)); -// const size_t elementsWritten = fwrite(&numBlocks, sizeof(numBlocks), 1, m_resources.IndexStream); -// if ( elementsWritten != 1 ) if ( numBytesWritten != sizeof(numBlocks) ) throw BamException("BamToolsIndex::WriteReferenceEntry", "could not write number of blocks"); diff --git a/src/api/internal/index/BamToolsIndex_p.h b/src/api/internal/index/BamToolsIndex_p.h index f6ffb72..7a66f39 100644 --- a/src/api/internal/index/BamToolsIndex_p.h +++ b/src/api/internal/index/BamToolsIndex_p.h @@ -2,7 +2,7 @@ // BamToolsIndex.h (c) 2010 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 10 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides index operations for the BamTools index format (".bti") // *************************************************************************** @@ -165,7 +165,6 @@ class BamToolsIndex : public BamIndex { Version m_outputVersion; struct RaiiWrapper { - FILE* IndexStream; IBamIODevice* Device; RaiiWrapper(void); ~RaiiWrapper(void); diff --git a/src/api/internal/io/BamFile_p.cpp b/src/api/internal/io/BamFile_p.cpp index 2bb0715..990d9bf 100644 --- a/src/api/internal/io/BamFile_p.cpp +++ b/src/api/internal/io/BamFile_p.cpp @@ -2,7 +2,7 @@ // BamFile_p.cpp (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides BAM file-specific IO behavior // *************************************************************************** diff --git a/src/api/internal/io/BamFile_p.h b/src/api/internal/io/BamFile_p.h index dd93894..ed61813 100644 --- a/src/api/internal/io/BamFile_p.h +++ b/src/api/internal/io/BamFile_p.h @@ -2,7 +2,7 @@ // BamFile_p.h (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides BAM file-specific IO behavior // *************************************************************************** diff --git a/src/api/internal/io/BamFtp_p.cpp b/src/api/internal/io/BamFtp_p.cpp index c6d3bf8..d9f933c 100644 --- a/src/api/internal/io/BamFtp_p.cpp +++ b/src/api/internal/io/BamFtp_p.cpp @@ -2,7 +2,7 @@ // BamFtp_p.cpp (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 8 November 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides reading/writing of BAM files on FTP server // *************************************************************************** @@ -13,8 +13,6 @@ using namespace BamTools; using namespace BamTools::Internal; -#include // debug - #include #include #include @@ -28,12 +26,14 @@ namespace Internal { // constants // ----------- -static const uint16_t FTP_PORT = 21; -static const string FTP_PREFIX = "ftp://"; -static const size_t FTP_PREFIX_LENGTH = 6; -static const string FTP_NEWLINE = "\r\n"; +static const uint16_t FTP_PORT = 21; +static const string FTP_PREFIX = "ftp://"; +static const size_t FTP_PREFIX_LENGTH = 6; +static const string FTP_NEWLINE = "\r\n"; + static const string DEFAULT_USER = "anonymous"; static const string DEFAULT_PASS = "anonymous@"; + static const string ABOR_CMD = "ABOR"; static const string USER_CMD = "USER"; static const string PASS_CMD = "PASS"; @@ -42,14 +42,16 @@ static const string REIN_CMD = "REIN"; static const string REST_CMD = "REST"; static const string RETR_CMD = "RETR"; static const string TYPE_CMD = "TYPE"; -static const char COLON_CHAR = ':'; -static const char COMMA_CHAR = ','; -static const char DOT_CHAR = '.'; -static const char MINUS_CHAR = '-'; -static const char SLASH_CHAR = '/'; -static const char SPACE_CHAR = ' '; -static const char LEFT_PAREN_CHAR = '('; -static const char RIGHT_PAREN_CHAR = ')'; + +static const char CMD_SEPARATOR = ' '; +static const char HOST_SEPARATOR = '/'; +static const char IP_SEPARATOR = '.'; + +static const char MULTILINE_CONTINUE = '-'; + +static const char PASV_REPLY_PREFIX = '('; +static const char PASV_REPLY_SEPARATOR = ','; +static const char PASV_REPLY_SUFFIX = ')'; // ----------------- // utility methods @@ -145,21 +147,21 @@ bool BamFtp::ConnectCommandSocket(void) { } // send USER command - string userCommand = USER_CMD + SPACE_CHAR + m_username + FTP_NEWLINE; + string userCommand = USER_CMD + CMD_SEPARATOR + m_username + FTP_NEWLINE; if ( !SendCommand(userCommand, true) ) { Close(); return false; } // send PASS command - string passwordCommand = PASS_CMD + SPACE_CHAR + m_password + FTP_NEWLINE; + string passwordCommand = PASS_CMD + CMD_SEPARATOR + m_password + FTP_NEWLINE; if ( !SendCommand(passwordCommand, true) ) { Close(); return false; } // send TYPE command - string typeCommand = TYPE_CMD + SPACE_CHAR + "I" + FTP_NEWLINE; + string typeCommand = TYPE_CMD + CMD_SEPARATOR + 'I' + FTP_NEWLINE; if ( !SendCommand(typeCommand, true) ) { Close(); return false; @@ -199,7 +201,7 @@ bool BamFtp::ConnectDataSocket(void) { stringstream fpStream(""); fpStream << m_filePosition; - string restartCommand = REST_CMD + SPACE_CHAR + fpStream.str() + FTP_NEWLINE; + string restartCommand = REST_CMD + CMD_SEPARATOR + fpStream.str() + FTP_NEWLINE; if ( !SendCommand(restartCommand, true) ) { // TODO: set error string return false; @@ -207,7 +209,7 @@ bool BamFtp::ConnectDataSocket(void) { } // main file retrieval request - string retrieveCommand = RETR_CMD + SPACE_CHAR + m_filename + FTP_NEWLINE; + string retrieveCommand = RETR_CMD + CMD_SEPARATOR + m_filename + FTP_NEWLINE; if ( !SendCommand(retrieveCommand, false) ) { // TODO: set error string return false; @@ -268,8 +270,8 @@ bool BamFtp::ParsePassiveResponse(void) { return false; // find parentheses - const size_t leftParenFound = m_response.find(LEFT_PAREN_CHAR); - const size_t rightParenFound = m_response.find(RIGHT_PAREN_CHAR); + const size_t leftParenFound = m_response.find(PASV_REPLY_PREFIX); + const size_t rightParenFound = m_response.find(PASV_REPLY_SUFFIX); if ( leftParenFound == string::npos || rightParenFound == string::npos ) return false; @@ -278,14 +280,14 @@ bool BamFtp::ParsePassiveResponse(void) { const string hostAndPort(responseBegin+leftParenFound+1, responseBegin+rightParenFound); // parse into string fields - vector fields = split(hostAndPort, COMMA_CHAR); + vector fields = split(hostAndPort, PASV_REPLY_SEPARATOR); if ( fields.size() != 6 ) return false; // fetch passive connection IP - m_dataHostname = fields[0] + DOT_CHAR + - fields[1] + DOT_CHAR + - fields[2] + DOT_CHAR + + m_dataHostname = fields[0] + IP_SEPARATOR + + fields[1] + IP_SEPARATOR + + fields[2] + IP_SEPARATOR + fields[3]; // fetch passive connection port @@ -310,7 +312,7 @@ void BamFtp::ParseUrl(const string& url) { return; // find end of host name portion (first '/' hit after the prefix) - const size_t firstSlashFound = tempUrl.find(SLASH_CHAR, FTP_PREFIX_LENGTH); + const size_t firstSlashFound = tempUrl.find(HOST_SEPARATOR, FTP_PREFIX_LENGTH); if ( firstSlashFound == string::npos ) { ; // no slash found... no filename given along with host? } @@ -403,7 +405,7 @@ bool BamFtp::ReceiveReply(void) { isdigit(headerLine[0]) && isdigit(headerLine[1]) && isdigit(headerLine[2]) && - ( headerLine[3] != MINUS_CHAR ) + ( headerLine[3] != MULTILINE_CONTINUE ) ) { headerEnd = true; diff --git a/src/api/internal/io/BamFtp_p.h b/src/api/internal/io/BamFtp_p.h index cedf716..11f549c 100644 --- a/src/api/internal/io/BamFtp_p.h +++ b/src/api/internal/io/BamFtp_p.h @@ -2,7 +2,7 @@ // BamFtp_p.h (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 10 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides reading/writing of BAM files on FTP server // *************************************************************************** @@ -61,7 +61,8 @@ class BamFtp : public IBamIODevice { // data members private: - // our main socket + + // our main sockets TcpSocket* m_commandSocket; TcpSocket* m_dataSocket; diff --git a/src/api/internal/io/BamHttp_p.cpp b/src/api/internal/io/BamHttp_p.cpp index 30d2c14..e2ade70 100644 --- a/src/api/internal/io/BamHttp_p.cpp +++ b/src/api/internal/io/BamHttp_p.cpp @@ -2,7 +2,7 @@ // BamHttp_p.cpp (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 8 November 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides reading/writing of BAM files on HTTP server // *************************************************************************** @@ -30,8 +30,16 @@ namespace Internal { static const string HTTP_PORT = "80"; static const string HTTP_PREFIX = "http://"; static const size_t HTTP_PREFIX_LENGTH = 7; -static const char COLON_CHAR = ':'; -static const char SLASH_CHAR = '/'; + +static const string DOUBLE_NEWLINE = "\n\n"; + +static const string GET_METHOD = "GET"; +static const string HOST_HEADER = "Host"; +static const string RANGE_HEADER = "Range"; +static const string BYTES_PREFIX = "bytes="; + +static const char HOST_SEPARATOR = '/'; +static const char PROXY_SEPARATOR = ':'; // ----------------- // utility methods @@ -177,14 +185,14 @@ void BamHttp::ParseUrl(const string& url) { return; // find end of host name portion (first '/' hit after the prefix) - const size_t firstSlashFound = tempUrl.find(SLASH_CHAR, HTTP_PREFIX_LENGTH); + const size_t firstSlashFound = tempUrl.find(HOST_SEPARATOR, HTTP_PREFIX_LENGTH); if ( firstSlashFound == string::npos ) { ; // no slash found... no filename given along with host? } // fetch hostname (check for proxy port) string hostname = tempUrl.substr(HTTP_PREFIX_LENGTH, (firstSlashFound - HTTP_PREFIX_LENGTH)); - const size_t colonFound = hostname.find(COLON_CHAR); + const size_t colonFound = hostname.find(PROXY_SEPARATOR); if ( colonFound != string::npos ) { ; // TODO: handle proxy port (later, just skip for now) } else { @@ -234,7 +242,8 @@ int64_t BamHttp::Read(char* data, const unsigned int numBytes) { // there is data left from last request if ( m_endRangeFilePosition > m_filePosition ) { - // try to read either the total 'remainingBytes' or whatever we have remaining from last request range + // try to read either the total 'remainingBytes' or + // whatever we have remaining from last request range const size_t rangeRemainingBytes = m_endRangeFilePosition - m_filePosition; const size_t bytesToRead = std::min(remainingBytes, rangeRemainingBytes); const int64_t socketBytesRead = ReadFromSocket(data+bytesReadSoFar, bytesToRead); @@ -244,7 +253,8 @@ int64_t BamHttp::Read(char* data, const unsigned int numBytes) { m_filePosition += socketBytesRead; } - // otherwise, this is a 1st-time read OR we already read everything from the last GET request + // otherwise, this is a 1st-time read or + // we already read everything from the last GET request else { // request for next range @@ -281,13 +291,12 @@ bool BamHttp::ReceiveResponse(void) { // fetch header, up until double new line string responseHeader; - static const string doubleNewLine = "\n\n"; do { // read line & append to full header const string headerLine = m_socket->ReadLine(); responseHeader += headerLine; - } while ( !endsWith(responseHeader, doubleNewLine) ); + } while ( !endsWith(responseHeader, DOUBLE_NEWLINE) ); // sanity check if ( responseHeader.empty() ) { @@ -365,16 +374,16 @@ bool BamHttp::SendRequest(const size_t numBytes) { // create range string m_endRangeFilePosition = m_filePosition + numBytes; stringstream range(""); - range << "bytes=" << m_filePosition << "-" << m_endRangeFilePosition; + range << BYTES_PREFIX << m_filePosition << '-' << m_endRangeFilePosition; // make sure we're connected if ( !EnsureSocketConnection() ) return false; // create request - m_request = new HttpRequestHeader("GET", m_filename); - m_request->SetField("Host", m_hostname); - m_request->SetField("Range", range.str()); + m_request = new HttpRequestHeader(GET_METHOD, m_filename); + m_request->SetField(HOST_HEADER, m_hostname); + m_request->SetField(RANGE_HEADER, range.str()); // write request to socket const string requestHeader = m_request->ToString(); diff --git a/src/api/internal/io/BamHttp_p.h b/src/api/internal/io/BamHttp_p.h index fae9302..371ccce 100644 --- a/src/api/internal/io/BamHttp_p.h +++ b/src/api/internal/io/BamHttp_p.h @@ -2,7 +2,7 @@ // BamHttp_p.h (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 7 November 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides reading/writing of BAM files on HTTP server // *************************************************************************** diff --git a/src/api/internal/io/BamPipe_p.cpp b/src/api/internal/io/BamPipe_p.cpp index d700189..2d571fd 100644 --- a/src/api/internal/io/BamPipe_p.cpp +++ b/src/api/internal/io/BamPipe_p.cpp @@ -2,7 +2,7 @@ // BamPipe_p.cpp (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides BAM pipe-specific IO behavior // *************************************************************************** @@ -34,8 +34,8 @@ bool BamPipe::Open(const IBamIODevice::OpenMode mode) { else if ( mode == IBamIODevice::WriteOnly ) m_stream = freopen(0, "wb", stdout); else { - const string errorType = string( mode == IBamIODevice::ReadWrite ? "unsupported" - : "unknown" ); + const string errorType = string( (mode == IBamIODevice::ReadWrite) ? "unsupported" + : "unknown" ); const string message = errorType + " open mode requested"; SetErrorString("BamPipe::Open", message); return false; diff --git a/src/api/internal/io/BamPipe_p.h b/src/api/internal/io/BamPipe_p.h index 115cab9..1a95cc7 100644 --- a/src/api/internal/io/BamPipe_p.h +++ b/src/api/internal/io/BamPipe_p.h @@ -2,7 +2,7 @@ // BamPipe_p.h (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- // Provides BAM pipe-specific IO behavior // *************************************************************************** diff --git a/src/api/internal/io/ByteArray_p.cpp b/src/api/internal/io/ByteArray_p.cpp index 2bfdd1b..5f54c83 100644 --- a/src/api/internal/io/ByteArray_p.cpp +++ b/src/api/internal/io/ByteArray_p.cpp @@ -1,9 +1,16 @@ +// *************************************************************************** +// ByteArray_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides a dynamic, variable-length byte buffer +// *************************************************************************** + #include "api/internal/io/ByteArray_p.h" using namespace BamTools; using namespace BamTools::Internal; -#include // debug - #include #include using namespace std; diff --git a/src/api/internal/io/ByteArray_p.h b/src/api/internal/io/ByteArray_p.h index 89d9e0f..7e95f6e 100644 --- a/src/api/internal/io/ByteArray_p.h +++ b/src/api/internal/io/ByteArray_p.h @@ -1,6 +1,25 @@ +// *************************************************************************** +// ByteArray_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides a dynamic, variable-length byte buffer +// *************************************************************************** + #ifndef BYTEARRAY_P_H #define BYTEARRAY_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #include "api/api_global.h" #include #include diff --git a/src/api/internal/io/HostAddress_p.cpp b/src/api/internal/io/HostAddress_p.cpp index 9d4fc97..873087b 100644 --- a/src/api/internal/io/HostAddress_p.cpp +++ b/src/api/internal/io/HostAddress_p.cpp @@ -1,3 +1,12 @@ +// *************************************************************************** +// HostAddress_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides a generic IP address container +// *************************************************************************** + #include "api/internal/io/HostAddress_p.h" using namespace BamTools; using namespace BamTools::Internal; @@ -17,7 +26,7 @@ namespace Internal { // split a string into fields, on delimiter character static inline -vector split(const string& source, char delim) { +vector Split(const string& source, char delim) { stringstream ss(source); string field; vector fields; @@ -28,7 +37,7 @@ vector split(const string& source, char delim) { // return number of occurrences of @pattern in @source static inline -uint8_t countHits(const string& source, const string& pattern) { +uint8_t CountHits(const string& source, const string& pattern) { uint8_t count(0); size_t found = source.find(pattern); @@ -40,10 +49,10 @@ uint8_t countHits(const string& source, const string& pattern) { } static -bool parseIp4(const string& address, uint32_t& maybeIp4 ) { +bool ParseIp4(const string& address, uint32_t& maybeIp4 ) { // split IP address into string fields - vector addressFields = split(address, '.'); + vector addressFields = Split(address, '.'); if ( addressFields.size() != 4 ) return false; @@ -73,7 +82,7 @@ bool parseIp4(const string& address, uint32_t& maybeIp4 ) { } static -bool parseIp6(const string& address, uint8_t* maybeIp6 ) { +bool ParseIp6(const string& address, uint8_t* maybeIp6 ) { string tmp = address; @@ -84,13 +93,13 @@ bool parseIp6(const string& address, uint8_t* maybeIp6 ) { tmp = tmp.substr(0, percentFound); // split IP address into string fields - vector fields = split(tmp, ':'); + vector fields = Split(tmp, ':'); const uint8_t numFields = fields.size(); if ( numFields < 3 || numFields > 8 ) return false; // get number of '::' separators - const uint8_t numColonColons = countHits(tmp, "::"); + const uint8_t numColonColons = CountHits(tmp, "::"); if ( numFields == 8 && numColonColons > 1 ) return false; @@ -158,7 +167,7 @@ bool parseIp6(const string& address, uint8_t* maybeIp6 ) { // parse the IPv4 section uint32_t maybeIp4; - if ( !parseIp4(field, maybeIp4) ) + if ( !ParseIp4(field, maybeIp4) ) return false; // store IPv4 fields in IPv6 container @@ -274,10 +283,10 @@ void HostAddress::Clear(void) { memset(&m_ip6Address, 0, sizeof(IPv6Address)); m_ipString.clear(); - // this may feel funny, but cleared IP value (equivalent to '0.0.0.0') is technically valid IP - // and that's not really what this flag is checking + // this may feel funny, but cleared IP (equivalent to '0.0.0.0') is technically valid + // and that's not really what this flag is checking anyway // - // this flag is only false iff the string passed in is a 'plain-text' hostname (www.foo.bar) + // this flag is false *iff* the string passed in is a 'plain-text' hostname (www.foo.bar) m_hasIpAddress = true; } @@ -337,7 +346,7 @@ bool HostAddress::ParseAddress(void) { if ( found != string::npos ) { // try parse IP6 address uint8_t maybeIp6[16]; - if ( parseIp6(s, maybeIp6) ) { + if ( ParseIp6(s, maybeIp6) ) { SetAddress(maybeIp6); m_protocol = HostAddress::IPv6Protocol; return true; @@ -348,7 +357,7 @@ bool HostAddress::ParseAddress(void) { found = s.find('.'); if ( found != string::npos ) { uint32_t maybeIp4(0); - if ( parseIp4(s, maybeIp4) ) { + if ( ParseIp4(s, maybeIp4) ) { SetAddress(maybeIp4); m_protocol = HostAddress::IPv4Protocol; return true; diff --git a/src/api/internal/io/HostAddress_p.h b/src/api/internal/io/HostAddress_p.h index 7542b67..4c1b360 100644 --- a/src/api/internal/io/HostAddress_p.h +++ b/src/api/internal/io/HostAddress_p.h @@ -1,6 +1,25 @@ +// *************************************************************************** +// HostAddress_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides a generic IP address container +// *************************************************************************** + #ifndef HOSTADDRESS_P_H #define HOSTADDRESS_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #include "api/api_global.h" #include #include diff --git a/src/api/internal/io/HostInfo_p.cpp b/src/api/internal/io/HostInfo_p.cpp index 1431fb8..80343f1 100644 --- a/src/api/internal/io/HostInfo_p.cpp +++ b/src/api/internal/io/HostInfo_p.cpp @@ -1,3 +1,12 @@ +// *************************************************************************** +// HostInfo_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides DNS lookup functionality for hostname & its discovered addresses +// *************************************************************************** + #include "api/internal/io/HostInfo_p.h" using namespace BamTools; using namespace BamTools::Internal; @@ -16,7 +25,7 @@ using namespace BamTools::Internal; using namespace std; // ------------------------- -// HostInfo basics +// HostInfo implementation // ------------------------- HostInfo::HostInfo(void) @@ -64,9 +73,10 @@ void HostInfo::SetHostName(const string& name) { m_hostName = name; } -// ------------------------------ +// --------------------------------- // HostInfo::Lookup(host, port) -// ------------------------------ +// - the real "heavy-lifter" here +// --------------------------------- HostInfo HostInfo::Lookup(const string& hostname, const string& port) { diff --git a/src/api/internal/io/HostInfo_p.h b/src/api/internal/io/HostInfo_p.h index 5660a38..ad03d37 100644 --- a/src/api/internal/io/HostInfo_p.h +++ b/src/api/internal/io/HostInfo_p.h @@ -1,6 +1,25 @@ +// *************************************************************************** +// HostInfo_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides DNS lookup functionality for hostname/IP addresses +// *************************************************************************** + #ifndef HOSTINFO_P_H #define HOSTINFO_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #include "api/internal/io/HostAddress_p.h" #include #include diff --git a/src/api/internal/io/HttpHeader_p.cpp b/src/api/internal/io/HttpHeader_p.cpp index 1398d4c..c4f78b6 100644 --- a/src/api/internal/io/HttpHeader_p.cpp +++ b/src/api/internal/io/HttpHeader_p.cpp @@ -1,3 +1,13 @@ +// *************************************************************************** +// HttpHeader_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides a generic interface for parsing/generating HTTP headers, along +// with specialized request & response header types +// *************************************************************************** + #include "api/internal/io/HttpHeader_p.h" using namespace BamTools; using namespace BamTools::Internal; diff --git a/src/api/internal/io/HttpHeader_p.h b/src/api/internal/io/HttpHeader_p.h index 764ff63..6330235 100644 --- a/src/api/internal/io/HttpHeader_p.h +++ b/src/api/internal/io/HttpHeader_p.h @@ -1,6 +1,26 @@ +// *************************************************************************** +// HttpHeader_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides a generic interface for parsing/generating HTTP headers, along +// with specialized request & response header types +// *************************************************************************** + #ifndef HTTP_HEADER_P_H #define HTTP_HEADER_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #include "api/api_global.h" #include #include diff --git a/src/api/internal/io/NetUnix_p.h b/src/api/internal/io/NetUnix_p.h index 14b2132..8cf75f8 100644 --- a/src/api/internal/io/NetUnix_p.h +++ b/src/api/internal/io/NetUnix_p.h @@ -1,6 +1,25 @@ +// *************************************************************************** +// NetUnix_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides common networking-related includes, etc. for all UNIX-like systems +// *************************************************************************** + #ifndef NETUNIX_P_H #define NETUNIX_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #ifndef _WIN32 // <-- source files only include the proper Net*_p.h, but this is a double-check #include @@ -16,11 +35,5 @@ # define BT_SOCKLEN_T socklen_t #endif -namespace BamTools { -namespace Internal { - -} // namespace Internal -} // namespace BamTools - #endif // _WIN32 #endif // NETUNIX_P_H diff --git a/src/api/internal/io/NetWin_p.h b/src/api/internal/io/NetWin_p.h index fb138b2..bcef955 100644 --- a/src/api/internal/io/NetWin_p.h +++ b/src/api/internal/io/NetWin_p.h @@ -1,6 +1,27 @@ +// *************************************************************************** +// NetWin_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides common networking-related includes, etc. for Windows systems +// +// Note: only supports XP and later +// *************************************************************************** + #ifndef NETWIN_P_H #define NETWIN_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #ifdef _WIN32 // <-- source files only include the proper Net*_p.h, but this is a double-check #include // <-- should bring 'windows.h' along with it diff --git a/src/api/internal/io/RollingBuffer_p.cpp b/src/api/internal/io/RollingBuffer_p.cpp index ab29253..c3f709d 100644 --- a/src/api/internal/io/RollingBuffer_p.cpp +++ b/src/api/internal/io/RollingBuffer_p.cpp @@ -1,9 +1,20 @@ +// *************************************************************************** +// RollingBuffer_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 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 +// to buffer end. +// +// implementation note: basically a 'smart' wrapper around 1..* ByteArrays +// *************************************************************************** + #include "api/internal/io/RollingBuffer_p.h" using namespace BamTools; using namespace BamTools::Internal; -#include // for debug - #include #include #include @@ -231,42 +242,6 @@ size_t RollingBuffer::ReadLine(char* dest, size_t max) { return bytesReadSoFar; } -string RollingBuffer::ReadLine(size_t max) { - - ByteArray result; - result.Resize(max); - - size_t numBytesRead = 0; - - // if max not provided, we need to read incrementally - if ( max == 0 ) { - max = UINT_MAX; - - // make sure we leave room for null terminator - result.Resize(1); - - size_t readResult; - do { - result.Resize(std::min(max, result.Size()+m_bufferGrowth)); - readResult = ReadLine(result.Data() + numBytesRead, result.Size() - numBytesRead); - if ( readResult > 0 || numBytesRead == 0 ) - numBytesRead += readResult; - } while ( readResult == m_bufferGrowth && result[numBytesRead-1] != '\n'); - } - - // otherwise read line with provided max - else numBytesRead = ReadLine(result.Data(), result.Size()); - - // adjust byte array depending on numBytesRead - if ( numBytesRead == 0 ) - result.Clear(); - else - result.Resize(numBytesRead); - - // return string from byte array - return string(result.ConstData(), result.Size()); -} - const char* RollingBuffer::ReadPointer(void) const { // return null if empty buffer diff --git a/src/api/internal/io/RollingBuffer_p.h b/src/api/internal/io/RollingBuffer_p.h index 70f06f2..e995f26 100644 --- a/src/api/internal/io/RollingBuffer_p.h +++ b/src/api/internal/io/RollingBuffer_p.h @@ -1,6 +1,29 @@ +// *************************************************************************** +// RollingBuffer_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 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 +// to buffer end. +// +// implementation note: basically a 'smart' wrapper around 1..* ByteArrays +// *************************************************************************** + #ifndef ROLLINGBUFFER_P_H #define ROLLINGBUFFER_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #include "api/api_global.h" #include "api/internal/io/ByteArray_p.h" #include @@ -13,21 +36,32 @@ class RollingBuffer { // ctors & dtor public: - RollingBuffer(size_t growth); // inits buffer, new byte arrays will try to be of size @growth - ~RollingBuffer(void); // dtor + RollingBuffer(size_t growth); + ~RollingBuffer(void); // RollingBuffer interface public: - size_t BlockSize(void) const; // returns current buffer size - bool CanReadLine(void) const; // checks buffer for carriage return - void Chop(size_t n); // frees @n bytes from end of buffer - void Clear(void); // clears entire buffer structure - void Free(size_t n); // frees @n bytes from front of buffer - size_t IndexOf(char c) const; // checks buffer for @c - bool IsEmpty(void) const; // returns whether buffer contains data - size_t Read(char* dest, size_t max); // returns up to @maxLen bytes into @dest, returns exactly how many bytes were read from buffer + + // returns current buffer size + size_t BlockSize(void) const; + // checks buffer for new line + bool CanReadLine(void) const; + // frees @n bytes from end of buffer + void Chop(size_t n); + // clears entire buffer structure + void Clear(void); + // frees @n bytes from front of buffer + void Free(size_t n); + // checks buffer for @c + size_t IndexOf(char c) const; + // returns whether buffer contains data + bool IsEmpty(void) const; + // reads up to @maxLen bytes into @dest + // returns exactly how many bytes were read from buffer + size_t Read(char* dest, size_t max); + // reads until newline (or up to @maxLen bytes) + // returns exactly how many bytes were read from buffer size_t ReadLine(char* dest, size_t max); - std::string ReadLine(size_t max = 0); const char* ReadPointer(void) const; // returns a C-fxn compatible char* to byte data char* Reserve(size_t n); // ensures that buffer contains space for @n incoming bytes, returns write-able char* diff --git a/src/api/internal/io/TcpSocketEngine_p.cpp b/src/api/internal/io/TcpSocketEngine_p.cpp index d13b0bc..467eaeb 100644 --- a/src/api/internal/io/TcpSocketEngine_p.cpp +++ b/src/api/internal/io/TcpSocketEngine_p.cpp @@ -1,6 +1,18 @@ +// *************************************************************************** +// TcpSocketEngine_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides low-level implementation of TCP I/O +// *************************************************************************** + +// N.B. - this file contains the top-level, platform-independent logic. "Native" methods +// are called as needed from the TcpSocketEngine_.cpp files. Selection of the proper +// native method file should have been handled at build-time by CMake. + #include "api/internal/io/HostInfo_p.h" #include "api/internal/io/TcpSocketEngine_p.h" - using namespace BamTools; using namespace BamTools::Internal; diff --git a/src/api/internal/io/TcpSocketEngine_p.h b/src/api/internal/io/TcpSocketEngine_p.h index a87eafe..1a1a944 100644 --- a/src/api/internal/io/TcpSocketEngine_p.h +++ b/src/api/internal/io/TcpSocketEngine_p.h @@ -1,6 +1,25 @@ +// *************************************************************************** +// TcpSocketEngine_p.h (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides low-level implementation of TCP I/O +// *************************************************************************** + #ifndef TCPSOCKETENGINE_P_H #define TCPSOCKETENGINE_P_H +// ------------- +// W A R N I N G +// ------------- +// +// This file is not part of the BamTools API. It exists purely as an +// implementation detail. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. + #include "api/internal/io/HostAddress_p.h" #include "api/internal/io/TcpSocket_p.h" @@ -51,8 +70,7 @@ struct TcpSocketEngine { bool nativeConnect(const HostAddress& address, const uint16_t port); bool nativeCreateSocket(HostAddress::NetworkProtocol protocol); void nativeDisconnect(void); - bool nativeFetchConnectionParameters(void); - int64_t nativeNumBytesAvailable(void) const; + int64_t nativeNumBytesAvailable(void) const; int64_t nativeRead(char* dest, size_t max); int nativeSelect(int msecs, bool isRead) const; int64_t nativeWrite(const char* data, size_t length); diff --git a/src/api/internal/io/TcpSocketEngine_unix_p.cpp b/src/api/internal/io/TcpSocketEngine_unix_p.cpp index d24bfb9..35d8160 100644 --- a/src/api/internal/io/TcpSocketEngine_unix_p.cpp +++ b/src/api/internal/io/TcpSocketEngine_unix_p.cpp @@ -1,3 +1,12 @@ +// *************************************************************************** +// TcpSocketEngine_unix_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides low-level implementation of TCP I/O for all UNIX-like systems +// *************************************************************************** + #include "api/internal/io/TcpSocketEngine_p.h" #include "api/internal/io/NetUnix_p.h" using namespace BamTools; @@ -151,7 +160,8 @@ bool TcpSocketEngine::nativeConnect(const HostAddress& address, const uint16_t p bool TcpSocketEngine::nativeCreateSocket(HostAddress::NetworkProtocol protocol) { // get protocol value for requested protocol type - const int protocolNum = ( (protocol == HostAddress::IPv6Protocol) ? AF_INET6 : AF_INET ); + const int protocolNum = ( (protocol == HostAddress::IPv6Protocol) ? AF_INET6 + : AF_INET ); // attempt to create socket int socketFd = socket(protocolNum, SOCK_STREAM, IPPROTO_TCP); @@ -253,11 +263,10 @@ int64_t TcpSocketEngine::nativeRead(char* dest, size_t max) { break; } } - return static_cast(ret); } -// negative value for msecs will block (forever) until +// negative value for msecs will block (forever) until ready int TcpSocketEngine::nativeSelect(int msecs, bool isRead) const { // set up FD set @@ -298,6 +307,5 @@ int64_t TcpSocketEngine::nativeWrite(const char* data, size_t length) { break; } } - return static_cast(writtenBytes); } diff --git a/src/api/internal/io/TcpSocketEngine_win_p.cpp b/src/api/internal/io/TcpSocketEngine_win_p.cpp index 6438b12..cb3ddca 100644 --- a/src/api/internal/io/TcpSocketEngine_win_p.cpp +++ b/src/api/internal/io/TcpSocketEngine_win_p.cpp @@ -1,3 +1,12 @@ +// *************************************************************************** +// TcpSocketEngine_win_p.cpp (c) 2011 Derek Barnett +// Marth Lab, Department of Biology, Boston College +// --------------------------------------------------------------------------- +// Last modified: 10 November 2011 (DB) +// --------------------------------------------------------------------------- +// Provides low-level implementation of TCP I/O for all Windows systems +// *************************************************************************** + #include "api/internal/io/TcpSocketEngine_p.h" #include "api/internal/io/NetWin_p.h" using namespace BamTools; @@ -13,31 +22,31 @@ using namespace std; namespace BamTools { namespace Internal { -static inline -void getPortAndAddress(const sockaddr* s, uint16_t& port, HostAddress& address) { - - // IPv6 - if (s->sa_family == AF_INET6) { - sockaddr_in6* ip6 = (sockaddr_in6*)s; - port = ntohs(ip6->sin6_port); - IPv6Address tmp; - memcpy(&tmp, &ip6->sin6_addr.in6_addr, sizeof(tmp)); - address.SetAddress(tmp); - return; - } - - // IPv4 - if ( s->sa_family == AF_INET ) { - sockaddr_in* ip4 = (sockaddr_in*)s; - port = ntohl(ip4->sin_port); - address.SetAddress( ntohl(ip4->sin_addr) ); - return; - } - - // should be unreachable - BT_ASSERT_X(false, "TcpSocketEngine::getPortAndAddress() : unknown network protocol "); - return false; -} +//static inline +//void getPortAndAddress(const sockaddr* s, uint16_t& port, HostAddress& address) { + +// // IPv6 +// if (s->sa_family == AF_INET6) { +// sockaddr_in6* ip6 = (sockaddr_in6*)s; +// port = ntohs(ip6->sin6_port); +// IPv6Address tmp; +// memcpy(&tmp, &ip6->sin6_addr.in6_addr, sizeof(tmp)); +// address.SetAddress(tmp); +// return; +// } + +// // IPv4 +// if ( s->sa_family == AF_INET ) { +// sockaddr_in* ip4 = (sockaddr_in*)s; +// port = ntohl(ip4->sin_port); +// address.SetAddress( ntohl(ip4->sin_addr) ); +// return; +// } + +// // should be unreachable +// BT_ASSERT_X(false, "TcpSocketEngine::getPortAndAddress() : unknown network protocol "); +// return false; +//} } // namespace Internal } // namespace BamTools @@ -47,257 +56,258 @@ void getPortAndAddress(const sockaddr* s, uint16_t& port, HostAddress& address) // -------------------------------- void TcpSocketEngine::nativeClose(void) { - close(m_socketDescriptor); + +// close(m_socketDescriptor); } bool TcpSocketEngine::nativeConnect(const HostAddress& address, const uint16_t port) { // setup connection parameters from address/port - sockaddr_in sockAddrIPv4; - sockaddr_in6 sockAddrIPv6; - sockaddr* sockAddrPtr = 0; - BT_SOCKLEN_T sockAddrSize = 0; - - // IPv6 - if ( address.GetProtocol() == HostAddress::IPv6Protocol ) { - - memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); - sockAddrIPv6.sin6_family = AF_INET6; - sockAddrIPv6.sin6_port = htons(port); - - IPv6Address ip6 = address.GetIPv6Address(); - memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6)); - - sockAddrSize = sizeof(sockAddrIPv6); - sockAddrPtr = (sockaddr*)&sockAddrIPv6; - } - - // IPv4 - else if ( address.GetProtocol() == HostAddress::IPv4Protocol ) { - - memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); - sockAddrIPv4.sin_family = AF_INET; - sockAddrIPv4.sin_port = htons(port); - sockAddrIPv4.sin_addr.s_addr = htonl(address.GetIPv4Address()); - - sockAddrSize = sizeof(sockAddrIPv4); - sockAddrPtr = (sockaddr*)&sockAddrIPv4; - } - - // unknown (should be unreachable) - else BT_ASSERT_X(false, "TcpSocketEngine::nativeConnect() : unknown network protocol"); - - // attempt conenction - int connectResult = connect(socketDescriptor, sockAddrPtr, sockAddrSize); - - // if hit error - if ( connectResult == -1 ) { - - // see what error was encountered - switch ( errno ) { - - case EISCONN: - m_socketState = TcpSocket::ConnectedState; - break; - case ECONNREFUSED: - case EINVAL: - m_socketError = TcpSocket::ConnectionRefusedError; - m_socketState = TcpSocket::UnconnectedState; - m_errorString = "connection refused"; - break; - case ETIMEDOUT: - m_socketError = TcpSocket::NetworkError; - m_errorString = "connection timed out"; - break; - case EHOSTUNREACH: - m_socketError = TcpSocket::NetworkError; - m_socketState = TcpSocket::UnconnectedState; - m_errorString = "host unreachable"; - break; - case ENETUNREACH: - m_socketError = TcpSocket::NetworkError; - m_socketState = TcpSocket::UnconnectedState; - m_errorString = "network unreachable"; - break; - case EADDRINUSE: - m_socketError = TcpSocket::NetworkError; - m_errorString = "address already in use"; - break; - case EACCES: - case EPERM: - m_socketError = TcpSocket::SocketAccessError; - m_socketState = TcpSocket::UnconnectedState; - m_errorString = "permission denied"; - case EAFNOSUPPORT: - case EBADF: - case EFAULT: - case ENOTSOCK: - m_socketState = TcpSocket::UnconnectedState; - default: - break; - } - - if ( m_socketState != TcpSocket::ConnectedState ) - return false; - } - - // otherwise, we should be good - // update state & return success - m_socketState = TcpSocket::ConnectedState; - return true; +// sockaddr_in sockAddrIPv4; +// sockaddr_in6 sockAddrIPv6; +// sockaddr* sockAddrPtr = 0; +// BT_SOCKLEN_T sockAddrSize = 0; + +// // IPv6 +// if ( address.GetProtocol() == HostAddress::IPv6Protocol ) { + +// memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6)); +// sockAddrIPv6.sin6_family = AF_INET6; +// sockAddrIPv6.sin6_port = htons(port); + +// IPv6Address ip6 = address.GetIPv6Address(); +// memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6)); + +// sockAddrSize = sizeof(sockAddrIPv6); +// sockAddrPtr = (sockaddr*)&sockAddrIPv6; +// } + +// // IPv4 +// else if ( address.GetProtocol() == HostAddress::IPv4Protocol ) { + +// memset(&sockAddrIPv4, 0, sizeof(sockAddrIPv4)); +// sockAddrIPv4.sin_family = AF_INET; +// sockAddrIPv4.sin_port = htons(port); +// sockAddrIPv4.sin_addr.s_addr = htonl(address.GetIPv4Address()); + +// sockAddrSize = sizeof(sockAddrIPv4); +// sockAddrPtr = (sockaddr*)&sockAddrIPv4; +// } + +// // unknown (should be unreachable) +// else BT_ASSERT_X(false, "TcpSocketEngine::nativeConnect() : unknown network protocol"); + +// // attempt conenction +// int connectResult = connect(socketDescriptor, sockAddrPtr, sockAddrSize); + +// // if hit error +// if ( connectResult == -1 ) { + +// // see what error was encountered +// switch ( errno ) { + +// case EISCONN: +// m_socketState = TcpSocket::ConnectedState; +// break; +// case ECONNREFUSED: +// case EINVAL: +// m_socketError = TcpSocket::ConnectionRefusedError; +// m_socketState = TcpSocket::UnconnectedState; +// m_errorString = "connection refused"; +// break; +// case ETIMEDOUT: +// m_socketError = TcpSocket::NetworkError; +// m_errorString = "connection timed out"; +// break; +// case EHOSTUNREACH: +// m_socketError = TcpSocket::NetworkError; +// m_socketState = TcpSocket::UnconnectedState; +// m_errorString = "host unreachable"; +// break; +// case ENETUNREACH: +// m_socketError = TcpSocket::NetworkError; +// m_socketState = TcpSocket::UnconnectedState; +// m_errorString = "network unreachable"; +// break; +// case EADDRINUSE: +// m_socketError = TcpSocket::NetworkError; +// m_errorString = "address already in use"; +// break; +// case EACCES: +// case EPERM: +// m_socketError = TcpSocket::SocketAccessError; +// m_socketState = TcpSocket::UnconnectedState; +// m_errorString = "permission denied"; +// case EAFNOSUPPORT: +// case EBADF: +// case EFAULT: +// case ENOTSOCK: +// m_socketState = TcpSocket::UnconnectedState; +// default: +// break; +// } + +// if ( m_socketState != TcpSocket::ConnectedState ) +// return false; +// } + +// // otherwise, we should be good +// // update state & return success +// m_socketState = TcpSocket::ConnectedState; +// return true; } bool TcpSocketEngine::nativeCreateSocket(HostAddress::NetworkProtocol protocol) { - // get protocol value for requested protocol type - const int protocolNum = ( (protocol == HostAddress::IPv6Protocol) ? AF_INET6 : AF_INET ); - - // attempt to create socket - int socketFd = socket(protocolNum, SOCK_STREAM, IPPROTO_TCP); - - // if we fetched an invalid socket descriptor - if ( socketFd <= 0 ) { - - // see what error we got - switch ( errno ) { - case EPROTONOSUPPORT: - case EAFNOSUPPORT: - case EINVAL: - m_socketError = TcpSocket::UnsupportedSocketOperationError; - m_errorString = "protocol not supported"; - break; - case ENFILE: - case EMFILE: - case ENOBUFS: - case ENOMEM: - m_socketError = TcpSocket::SocketResourceError; - m_errorString = "out of resources"; - break; - case EACCES: - m_socketError = TcpSocket::SocketAccessError; - m_errorString = "permission denied"; - break; - default: - break; - } - - // return failure - return false; - } - - // otherwise, store our socket FD & return success - m_socketDescriptor = socketFd; - return true; +// // get protocol value for requested protocol type +// const int protocolNum = ( (protocol == HostAddress::IPv6Protocol) ? AF_INET6 : AF_INET ); + +// // attempt to create socket +// int socketFd = socket(protocolNum, SOCK_STREAM, IPPROTO_TCP); + +// // if we fetched an invalid socket descriptor +// if ( socketFd <= 0 ) { + +// // see what error we got +// switch ( errno ) { +// case EPROTONOSUPPORT: +// case EAFNOSUPPORT: +// case EINVAL: +// m_socketError = TcpSocket::UnsupportedSocketOperationError; +// m_errorString = "protocol not supported"; +// break; +// case ENFILE: +// case EMFILE: +// case ENOBUFS: +// case ENOMEM: +// m_socketError = TcpSocket::SocketResourceError; +// m_errorString = "out of resources"; +// break; +// case EACCES: +// m_socketError = TcpSocket::SocketAccessError; +// m_errorString = "permission denied"; +// break; +// default: +// break; +// } + +// // return failure +// return false; +// } + +// // otherwise, store our socket FD & return success +// m_socketDescriptor = socketFd; +// return true; } -bool TcpSocketEngine::nativeFetchConnectionParameters(void) { - - // reset addresses/ports - m_localAddress.Clear(); - m_remoteAddress.Clear(); - m_localPort = 0; - m_remotePort = 0; - - // skip (return failure) if invalid socket FD - if ( m_socketDescriptor == -1 ) - return false; - - sockaddr sa; - BT_SOCKLEN_T sockAddrSize = sizeof(sa); - - // fetch local address info - memset(&sa, 0, sizeof(sa)); - if ( getsockname(m_socketDescriptor, &sa, &sockAddrSize) == 0 ) { - getPortAndAddress(&sa, m_localPort, m_localAddress); - } - else if ( errno == EBADF ) { - m_socketError = TcpSocket::UnsupportedSocketOperationError; - m_errorString = "invalid socket descriptor"; - return false; - } - - // fetch remote address - if ( getpeername(m_socketDescriptor, &sa, &sockAddrSize) == 0 ) - getPortAndAddress(&sa, m_remotePort, m_remoteAddress); - - // return success - return true; -} +//bool TcpSocketEngine::nativeFetchConnectionParameters(void) { + +// // reset addresses/ports +// m_localAddress.Clear(); +// m_remoteAddress.Clear(); +// m_localPort = 0; +// m_remotePort = 0; + +// // skip (return failure) if invalid socket FD +// if ( m_socketDescriptor == -1 ) +// return false; + +// sockaddr sa; +// BT_SOCKLEN_T sockAddrSize = sizeof(sa); + +// // fetch local address info +// memset(&sa, 0, sizeof(sa)); +// if ( getsockname(m_socketDescriptor, &sa, &sockAddrSize) == 0 ) { +// getPortAndAddress(&sa, m_localPort, m_localAddress); +// } +// else if ( errno == EBADF ) { +// m_socketError = TcpSocket::UnsupportedSocketOperationError; +// m_errorString = "invalid socket descriptor"; +// return false; +// } + +// // fetch remote address +// if ( getpeername(m_socketDescriptor, &sa, &sockAddrSize) == 0 ) +// getPortAndAddress(&sa, m_remotePort, m_remoteAddress); + +// // return success +// return true; +//} size_t TcpSocketEngine::nativeNumBytesAvailable(void) const { - // fetch number of bytes, return 0 on error - int numBytes(0); - if ( ioctl(m_socketDescriptor, FIONREAD, (char*)&numBytes) < 0 ) - return 0; - return static_cast(numBytes); +// // fetch number of bytes, return 0 on error +// int numBytes(0); +// if ( ioctl(m_socketDescriptor, FIONREAD, (char*)&numBytes) < 0 ) +// return 0; +// return static_cast(numBytes); } int64_t TcpSocketEngine::nativeRead(char* dest, size_t max) { - if ( !IsValid() ) - return -1; - - ssize_t ret = read(m_socketDescriptor, dest, max); - if ( ret < 0 ) { - ret = -1; - switch ( errno ) { - case EAGAIN : - // No data was available for reading - ret = -2; - break; - case ECONNRESET : - ret = 0; - break; - default: - break; - } - } - - return static_cast(ret); +// if ( !IsValid() ) +// return -1; + +// ssize_t ret = read(m_socketDescriptor, dest, max); +// if ( ret < 0 ) { +// ret = -1; +// switch ( errno ) { +// case EAGAIN : +// // No data was available for reading +// ret = -2; +// break; +// case ECONNRESET : +// ret = 0; +// break; +// default: +// break; +// } +// } + +// return static_cast(ret); } // negative value for msecs will block (forever) until int TcpSocketEngine::nativeSelect(int msecs, bool isRead) const { - // set up FD set - fd_set fds; - FD_ZERO(&fds); - FD_SET(m_socketDescriptor, &fds); - - // setup our timeout - timeval tv; - tv.tv_sec = msecs / 1000; - tv.tv_usec = (msecs % 1000) * 1000; - - // do 'select' - int ret; - if ( isRead ) - ret = select(m_socketDescriptor + 1, &fds, 0, 0, (msecs < 0 ? 0 : &tv)); - else - ret = select(m_socketDescriptor + 1, 0, &fds, 0, (msecs < 0 ? 0 : &tv)); - return ret; +// // set up FD set +// fd_set fds; +// FD_ZERO(&fds); +// FD_SET(m_socketDescriptor, &fds); + +// // setup our timeout +// timeval tv; +// tv.tv_sec = msecs / 1000; +// tv.tv_usec = (msecs % 1000) * 1000; + +// // do 'select' +// int ret; +// if ( isRead ) +// ret = select(m_socketDescriptor + 1, &fds, 0, 0, (msecs < 0 ? 0 : &tv)); +// else +// ret = select(m_socketDescriptor + 1, 0, &fds, 0, (msecs < 0 ? 0 : &tv)); +// return ret; } int64_t TcpSocketEngine::nativeWrite(const char* data, size_t length) { - ssize_t writtenBytes = write(m_socketDescriptor, data, length); - if ( writtenBytes < 0 ) { - switch (errno) { - case EPIPE: - case ECONNRESET: - writtenBytes = -1; - m_socketError = TcpSocket::RemoteHostClosedError; - m_errorString = "remote host closed connection"; - Close(); - break; - case EAGAIN: - writtenBytes = 0; - break; - default: - break; - } - } - - return static_cast(writtenBytes); +// ssize_t writtenBytes = write(m_socketDescriptor, data, length); +// if ( writtenBytes < 0 ) { +// switch (errno) { +// case EPIPE: +// case ECONNRESET: +// writtenBytes = -1; +// m_socketError = TcpSocket::RemoteHostClosedError; +// m_errorString = "remote host closed connection"; +// Close(); +// break; +// case EAGAIN: +// writtenBytes = 0; +// break; +// default: +// break; +// } +// } + +// return static_cast(writtenBytes); } diff --git a/src/api/internal/io/TcpSocket_p.cpp b/src/api/internal/io/TcpSocket_p.cpp index 2f24b8b..4ff53a8 100644 --- a/src/api/internal/io/TcpSocket_p.cpp +++ b/src/api/internal/io/TcpSocket_p.cpp @@ -2,9 +2,9 @@ // TcpSocket_p.cpp (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- -// Provides generic TCP socket (buffered) I/O +// Provides basic TCP I/O interface // *************************************************************************** #include "api/internal/io/ByteArray_p.h" @@ -13,8 +13,6 @@ using namespace BamTools; using namespace BamTools::Internal; -#include // debug - #include #include #include diff --git a/src/api/internal/io/TcpSocket_p.h b/src/api/internal/io/TcpSocket_p.h index 9727423..3c5f2fc 100644 --- a/src/api/internal/io/TcpSocket_p.h +++ b/src/api/internal/io/TcpSocket_p.h @@ -2,9 +2,9 @@ // TcpSocket_p.h (c) 2011 Derek Barnett // Marth Lab, Department of Biology, Boston College // --------------------------------------------------------------------------- -// Last modified: 25 October 2011 (DB) +// Last modified: 10 November 2011 (DB) // --------------------------------------------------------------------------- -// Provides TCP socket I/O +// Provides basic TCP I/O interface // *************************************************************************** #ifndef TCPSOCKET_P_H -- 2.39.2