Advertisement
Guest User

TCPConnection.cpp

a guest
Dec 26th, 2013
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 38.77 KB | None | 0 0
  1. // Copyright (c) 2010 Martin Knafve / hMailServer.com.  
  2. // http://www.hmailserver.com
  3.  
  4. #include "StdAfx.h"
  5. #include "TCPConnection.h"
  6.  
  7. #include "ProtocolParser.h"
  8. #include "../Util/ByteBuffer.h"
  9.  
  10. #include "../BO/TCPIPPorts.h"
  11. #include "../TCPIP/LocalIPAddresses.h"
  12. #include "../TCPIP/IPAddress.h"
  13.  
  14. #include "../Persistence/PersistentSecurityRange.h"
  15.  
  16. #include "IOOperation.h"
  17.  
  18. #ifdef _DEBUG
  19. #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
  20. #define new DEBUG_NEW
  21. #endif
  22.  
  23. namespace HM
  24. {
  25.  
  26.  
  27.    TCPConnection::TCPConnection(bool useSSL,
  28.                                 boost::asio::io_service& io_service,
  29.                                 boost::asio::ssl::context& context) :
  30.       _useSSL(useSSL),
  31.       _socket(io_service),
  32.       _sslSocket(io_service, context),
  33.       _resolver(io_service),
  34.       _timer(io_service),
  35.       _receiveBinary(false),
  36.       _remotePort(0),
  37.       _hasTimeout(false),
  38.       _receiveBuffer(250000)
  39.    {
  40.     _handshakeDone = false;
  41.    }
  42.  
  43.    TCPConnection::~TCPConnection(void)
  44.    {
  45.       try
  46.       {
  47.          _connectionTermination.Set();
  48.          
  49.       }
  50.       catch (...)
  51.       {
  52.          ReportError(ErrorManager::Low, 5139, "TCPConnection::~TCPConnection", "An error occurred while setting connection termination flag.");
  53.          throw;
  54.       }
  55.  
  56.       CancelLogoutTimer();
  57.    }
  58.  
  59.    ssl_socket::lowest_layer_type&
  60.    TCPConnection::GetSocket()
  61.    {
  62.        LOG_DEBUG("TCPConnection::GetSocket()");
  63.       if (_useSSL)
  64.           if (_handshakeDone == false){
  65.               LOG_DEBUG("TCPCconnection::GetSocket(): lowest_layer()");
  66.               return _sslSocket.next_layer();
  67.           } else {
  68.               LOG_DEBUG("TCPCconnection::GetSocket(): SSL Layer");
  69.               return _sslSocket.lowest_layer();
  70.           }
  71.       else
  72.          return _socket;
  73.    }
  74.  
  75.    bool
  76.    TCPConnection::Connect(const AnsiString &remoteServer, long remotePort, const IPAddress &localAddress)
  77.    {
  78.       try
  79.       {
  80.          LOG_TCPIP("Connecting to " + remoteServer + "...");
  81.  
  82.          _remotePort = remotePort;
  83.          _remoteServer = remoteServer;
  84.  
  85.          if (!localAddress.IsAny())
  86.          {
  87.  
  88.             try
  89.             {
  90.                if (localAddress.GetType() == IPAddress::IPV4)
  91.                   GetSocket().open(boost::asio::ip::tcp::v4());
  92.                else if (localAddress.GetType() == IPAddress::IPV6)
  93.                   GetSocket().open(boost::asio::ip::tcp::v6());
  94.                GetSocket().bind(boost::asio::ip::tcp::endpoint(localAddress.GetAddress(), 0));
  95.             }
  96.             catch (boost::system::system_error error)
  97.             {
  98.                try
  99.                {
  100.                   // this may throw...
  101.                   GetSocket().close();
  102.                }
  103.                catch (...)
  104.                {
  105.                   // shouldn't be an error.
  106.                }
  107.  
  108.  
  109.                String errorMessage = Formatter::Format("Failed to bind to IP address {0}.", localAddress.ToString());
  110.                ReportError(ErrorManager::Medium, 4330, "TCPConnection::Connect", errorMessage, error);
  111.  
  112.                return false;
  113.             }
  114.          }
  115.  
  116.    #ifdef _DEBUG
  117.          String sMessage;
  118.          sMessage.Format(_T("RESOLVE: %s\r\n"), String(remoteServer));
  119.    #endif
  120.  
  121.          // Start an asynchronous resolve to translate the server and service names
  122.          // into a list of endpoints.
  123.          AnsiString sPort = StringParser::IntToString(remotePort);
  124.          
  125.          boost::asio::ip::resolver_query_base::flags flags;
  126.  
  127.          if (StringParser::IsValidIPAddress(remoteServer))
  128.          {
  129.             flags = tcp::resolver::query::passive |
  130.                     tcp::resolver::query::numeric_host |
  131.                      tcp::resolver::query::numeric_service;
  132.          }
  133.          else
  134.          {
  135.             flags =  
  136.                tcp::resolver::query::passive |
  137.                tcp::resolver::query::numeric_service;
  138.          }
  139.  
  140.  
  141.          tcp::resolver::query query(remoteServer, sPort, flags);
  142.  
  143.          _resolver.async_resolve(query,
  144.             boost::bind(&TCPConnection::HandleResolve, shared_from_this(),
  145.             boost::asio::placeholders::error,
  146.             boost::asio::placeholders::iterator));
  147.  
  148.          return true;
  149.       }
  150.       catch (...)
  151.       {
  152.          String errorMessage = Formatter::Format("An unknown error occurred while connecting to {0} on port {1}", remoteServer, remotePort);
  153.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5321, "TCPConnection::Connect", errorMessage);
  154.          throw;
  155.       }
  156.    }
  157.  
  158.    void
  159.    TCPConnection::HandleResolve(const boost::system::error_code& err, tcp::resolver::iterator endpoint_iterator)
  160.    {
  161.       try
  162.       {
  163.          if (err)
  164.          {
  165.             AnsiString error = err.message();
  166.             if (_protocolParser)
  167.                _protocolParser->OnCouldNotConnect("Host name: " + _remoteServer + ", message: " + error);
  168.             return;
  169.          }
  170.  
  171.          _StartAsyncConnect(endpoint_iterator);
  172.       }
  173.       catch (...)
  174.       {
  175.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5322, "TCPConnection::Connect", "An unknown error occurred while handling TCP/IP resolve.");
  176.          throw;
  177.       }
  178.    }
  179.  
  180.    void
  181.    TCPConnection::_StartAsyncConnect(tcp::resolver::iterator endpoint_iterator)
  182.    {
  183.       try
  184.       {
  185.          // Check that we don't try to connect to a port we're listening on. Doing
  186.          // that could start evil loops.
  187.          tcp::endpoint endpoint = *endpoint_iterator;
  188.  
  189.          if (LocalIPAddresses::Instance()->IsLocalPort(endpoint.address(), _remotePort))
  190.          {
  191.             String sMessage;
  192.             sMessage.Format(_T("Could not connect to %s on port %d since this would mean connecting to myself."), _remoteServer, _remotePort);
  193.  
  194.             if (_protocolParser)
  195.                _protocolParser->OnCouldNotConnect(sMessage);
  196.  
  197.             LOG_TCPIP(_T("TCPConnection - ") + sMessage);
  198.  
  199.             return;
  200.          }
  201.  
  202.          // Attempt a connection to the first endpoint in the list. Each endpoint
  203.          // will be tried until we successfully establish a connection.
  204.          try
  205.          {
  206.             GetSocket().async_connect(endpoint,
  207.                boost::bind(&TCPConnection::HandleConnect, shared_from_this(),
  208.                boost::asio::placeholders::error, ++endpoint_iterator));
  209.          }
  210.          catch (boost::system::system_error error)
  211.          {
  212.             // We failed to send the data to the client. Log an message in the log,
  213.             // and switch of operation-in-progress flag. We don't log this as an
  214.             // error since it most likely isn't.
  215.             String sMessage;
  216.             sMessage.Format(_T("TCPConnection - Call to async_connect failed. Error code: %d, Message: %s"), error.code().value(), String(error.what()));
  217.             LOG_TCPIP(sMessage);
  218.          }
  219.       }
  220.       catch (...)
  221.       {
  222.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5323, "TCPConnection::_StartAsyncConnect", "An unknown error occurred while starting asynchronous connect.");
  223.          throw;
  224.       }
  225.    }
  226.  
  227.    void
  228.    TCPConnection::HandleConnect(const boost::system::error_code& err, tcp::resolver::iterator endpoint_iterator)
  229.    {
  230.        LOG_DEBUG("TCPConnection::HandleConnect");
  231.       try
  232.       {
  233.          if (err)
  234.          {
  235.             // Are there more addresses we should attempt to connect to?
  236.             if (endpoint_iterator != tcp::resolver::iterator())
  237.             {
  238.                GetSocket().close();
  239.  
  240.                // Attemp with the next address.
  241.                _StartAsyncConnect(endpoint_iterator);
  242.                
  243.                return;
  244.             }
  245.            
  246.             AnsiString error = err.message();
  247.  
  248.             if (_protocolParser)
  249.                _protocolParser->OnCouldNotConnect("Host name: " + _remoteServer + ", message: " + error);
  250.  
  251.             return;
  252.          }
  253.  
  254.          if (_useSSL)
  255.          {
  256.             LOG_DEBUG("HandleConnect, working on handshake");
  257.             boost::asio::ssl::stream_base::handshake_type handshakeType = IsClient() ?
  258.                boost::asio::ssl::stream_base::client :
  259.                boost::asio::ssl::stream_base::server;
  260.                
  261.             _sslSocket.async_handshake(handshakeType,
  262.                boost::bind(&TCPConnection::HandleHandshake, shared_from_this(),
  263.                boost::asio::placeholders::error));
  264.          }
  265.          else
  266.          {
  267.             // Send welcome message to client.
  268.             _protocolParser->OnConnected();
  269.          }
  270.       }
  271.       catch (...)
  272.       {
  273.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5324, "TCPConnection::HandleConnect", "An unknown error occurred while handling asynchronous connect.");
  274.          throw;
  275.       }
  276.    }
  277.  
  278.    void
  279.    TCPConnection::Start(shared_ptr<ProtocolParser> protocolParser)
  280.    {
  281.        LOG_DEBUG("TCPConnection::Start");
  282.       try
  283.       {
  284.          _protocolParser = protocolParser;
  285.          _protocolParser->Initialize(this);
  286.          startTLS = true;
  287.          if (GetSocket().is_open())
  288.             {
  289.                // Send welcome message to client.
  290.                _protocolParser->OnConnected();
  291.             }
  292.       }
  293.       catch (...)
  294.       {
  295.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5325, "TCPConnection::Start", "An unknown error occurred while starting connection.");
  296.          throw;
  297.       }
  298.    }
  299.  
  300.     void
  301.     TCPConnection::StartTLS(){
  302.         if (GetSocket().is_open())
  303.         {
  304.             startTLS=false;
  305.             _handshakeDone = false;
  306.             LOG_DEBUG("TCPConnection::StartTLS");
  307.             _sslSocket.async_handshake(boost::asio::ssl::stream_base::server,
  308.                 boost::bind(&TCPConnection::HandleHandshake, shared_from_this(),
  309.                 boost::asio::placeholders::error));
  310.         }
  311.     }
  312.  
  313.  
  314.  
  315.    void
  316.    TCPConnection::HandleHandshake(const boost::system::error_code& error)
  317.    {
  318.       LOG_DEBUG("TCPConnection::HandleHandshake");
  319.       try
  320.       {
  321.          if (!error)
  322.          {
  323.              _handshakeDone = true;
  324.             // Send welcome message to client.
  325.             _protocolParser->OnConnected();
  326.          }
  327.          else
  328.          {
  329.             // The SSL handshake failed. This may happen for example if the user who has connected
  330.             // to the TCP/IP port disconnects immediately without sending any data.
  331.             String sMessage;
  332.             sMessage.Format(_T("TCPConnection - SSL handshake with client failed. Error code: %d, Message: %s, Remote IP: %s"), error.value(), String(error.message()), SafeGetIPAddress());
  333.             LOG_TCPIP(sMessage);           
  334.          }
  335.       }
  336.       catch (...)
  337.       {
  338.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5326, "TCPConnection::HandleHandshake", "An unknown error occurred while handling handshake.");
  339.          throw;
  340.       }
  341.  
  342.    }
  343.  
  344.    void
  345.    TCPConnection::PostWrite(const AnsiString &sData)
  346.    {
  347.        LOG_DEBUG("TCPConnection::PostWrite(AnsiString)");
  348.       try
  349.       {
  350.          AnsiString sTemp = sData;
  351.          char *pBuf = sTemp.GetBuffer();
  352.          
  353.          shared_ptr<ByteBuffer> pBuffer = shared_ptr<ByteBuffer>(new ByteBuffer());
  354.          pBuffer->Add((BYTE*) pBuf, sData.GetLength());
  355.          
  356.    #ifdef _DEBUG
  357.          String sDebugOutput;
  358.          sDebugOutput.Format(_T("SENT: %s"), String(sTemp));
  359.          OutputDebugString(sDebugOutput);
  360.    #endif
  361.  
  362.          PostWrite(pBuffer);
  363.       }
  364.       catch (...)
  365.       {
  366.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5327, "TCPConnection::PostWrite", "An unknown error occurred while posting write buffer.");
  367.          throw;
  368.       }
  369.  
  370.    }
  371.  
  372.    void
  373.    TCPConnection::PostWrite(shared_ptr<ByteBuffer> pBuffer)
  374.    {
  375.        LOG_DEBUG("TCPConnection::PostWrite(pBuffer)");
  376.       try
  377.       {
  378.          shared_ptr<IOOperation> operation = shared_ptr<IOOperation>(new IOOperation(IOOperation::BCTSend, pBuffer));
  379.          _operationQueue.Push(operation);
  380.  
  381.          _ProcessOperationQueue();
  382.       }
  383.       catch (...)
  384.       {
  385.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5328, "TCPConnection::PostWrite", "An unknown error occurred while posting write buffer.");
  386.          throw;
  387.       }
  388.    }
  389.  
  390.    void
  391.    TCPConnection::_ProcessOperationQueue()
  392.    {
  393.        LOG_DEBUG("TCPConnection::_ProcessOperationQueue");
  394.        if ((_useSSL == true) && (startTLS==false) && (_handshakeDone == false)) return;
  395.       int stage = 0;
  396.  
  397.       try
  398.       {
  399.          stage = 1;
  400.          // Pick out the next item to process...
  401.          shared_ptr<IOOperation> operation = _operationQueue.Front();
  402.  
  403.          stage = 2;
  404.          if (!operation)
  405.          {
  406.             // We're no longer sending...
  407.              LOG_DEBUG("TCPConnection::_ProcessOperationQueue, stage 20");
  408.             stage = 20;
  409.             return;
  410.          }
  411.          stage = 3;
  412.  
  413.         switch (operation->GetType())
  414.          {
  415.          case IOOperation::BCTSend:
  416.             {
  417.                 LOG_DEBUG("TCPConnection::_ProcessOperationQueue,BCTSend");
  418.                stage = 4;
  419.                shared_ptr<ByteBuffer> pBuf = operation->GetBuffer();
  420.                Write(pBuf);
  421.                stage = 5;
  422.                break;
  423.             }
  424.          case IOOperation::BCTReceive:
  425.             {
  426.                 LOG_DEBUG("TCPConnection::_ProcessOperationQueue,BCTRead");
  427.                stage = 6;
  428.                Read(operation->GetString());              
  429.                stage = 7;
  430.                break;
  431.             }
  432.          case IOOperation::BCTShutdownSend:
  433.             {
  434.                 LOG_DEBUG("TCPConnection::_ProcessOperationQueue,BCTShutdownSend");
  435.                stage = 8;
  436.                Shutdown(boost::asio::ip::tcp::socket::shutdown_send, true);
  437.                stage = 9;
  438.                _ProcessOperationQueue();
  439.                stage = 10;
  440.  
  441.                break;
  442.             }
  443.          case IOOperation::BCTDisconnect:
  444.             {
  445.                     LOG_DEBUG("TCPConnection::_ProcessOperationQueue,BCTDisconnect");
  446.                stage = 11;
  447.                Disconnect();
  448.                stage = 12;
  449.                break;
  450.             }
  451.          }
  452.       }
  453.       catch (boost::system::system_error error)
  454.       {
  455.          ReportError(ErrorManager::Medium, 5138, "TCPConnection::_ProcessOperationQueue",
  456.             Formatter::Format("An error occured while processing the queue. Stage: {0}", stage), error);
  457.       }
  458.       catch (...)
  459.       {
  460.          ReportError(ErrorManager::Medium, 5138, "TCPConnection::_ProcessOperationQueue",
  461.             Formatter::Format("An error occured while processing the queue. Stage: {0}", stage));
  462.       }
  463.    }
  464.  
  465.    void
  466.    TCPConnection::ReportError(ErrorManager::eSeverity sev, int code, const String &context, const String &message, const boost::system::system_error &error)
  467.    {
  468.       String formattedMessage;
  469.       formattedMessage.Format(_T("%s Remote IP: %s, Error code: %d, Message: %s"), message, SafeGetIPAddress(), error.code().value(), String(error.what()));
  470.       ErrorManager::Instance()->ReportError(sev, code, context, formattedMessage);        
  471.    }
  472.  
  473.    void
  474.    TCPConnection::ReportError(ErrorManager::eSeverity sev, int code, const String &context, const String &message)
  475.    {
  476.       String formattedMessage;
  477.       formattedMessage.Format(_T("%s Remote IP: %s"), message, SafeGetIPAddress());
  478.       ErrorManager::Instance()->ReportError(sev, code, context, formattedMessage);        
  479.    }
  480.  
  481.    void
  482.    TCPConnection::ReportInitError(ErrorManager::eSeverity sev, int code, const String &context, const String &message, const boost::system::system_error &error)
  483.    {
  484.       String formattedMessage;
  485.       formattedMessage.Format(_T("%s, Error code: %d, Message: %s"), message, error.code().value(), String(error.what()));
  486.       ErrorManager::Instance()->ReportError(sev, code, context, formattedMessage);        
  487.    }
  488.  
  489.    void
  490.    TCPConnection::ReportDebugMessage(const String &message, const boost::system::error_code &error)
  491.    {
  492.       String formattedMessage;
  493.       formattedMessage.Format(_T("%s Remote IP: %s, Session: %d, Code: %d, Message: %s"), message, SafeGetIPAddress(), GetSessionID(), error.value(), String(error.message()));
  494.  
  495.       LOG_DEBUG(formattedMessage);
  496.    }
  497.  
  498.    void
  499.    TCPConnection::Write(shared_ptr<ByteBuffer> buffer)
  500.    {
  501.        //LOG_DEBUG("TCPConnection::Write");
  502.       try
  503.       {
  504.          int timeout = _protocolParser->GetTimeout();
  505.  
  506.          function<void (const boost::system::error_code&, size_t)> handleWriteFunction =
  507.             boost::bind(&TCPConnection::HandleWrite, shared_from_this(),
  508.             boost::asio::placeholders::error,
  509.             boost::asio::placeholders::bytes_transferred);
  510.          try
  511.          {
  512.              if (_useSSL){
  513.                 if (startTLS == true) {
  514.                     LOG_DEBUG("TCPConnection::Write, alternate");
  515.                     boost::asio::async_write
  516.                         (_sslSocket.next_layer(), boost::asio::buffer(buffer->GetCharBuffer(), buffer->GetSize()), handleWriteFunction);
  517.                 } else {
  518.                     LOG_DEBUG("TCPConnection::Write, SSL");
  519.                     boost::asio::async_write
  520.                         (_sslSocket, boost::asio::buffer(buffer->GetCharBuffer(), buffer->GetSize()), handleWriteFunction);
  521.                 }
  522.          } else
  523.                boost::asio::async_write
  524.                   (_socket, boost::asio::buffer(buffer->GetCharBuffer(), buffer->GetSize()), handleWriteFunction);
  525.  
  526.             UpdateLogoutTimer();
  527.          }
  528.          catch (boost::system::system_error error)
  529.          {
  530.             // We failed to send the data to the client. Log an message in the log,
  531.             // and switch of operation-in-progress flag. We don't log this as an
  532.             // error since it most likely isn't.
  533.             String sMessage;
  534.             sMessage.Format(_T("TCPConnection - Sending of data to client failed. Error code: %d, Message: %s, Remote IP: %s"), error.code().value(), String(error.what()), SafeGetIPAddress());
  535.             LOG_TCPIP(sMessage);
  536.          }
  537.          catch (std::exception const& e)
  538.          {
  539.             String sErrorMessage = Formatter::Format("Write operation failed. Error: {0}", e.what());
  540.             ErrorManager::Instance()->ReportError(ErrorManager::High, 4208, "Temp::Temp", sErrorMessage);
  541.          }
  542.          catch (...)
  543.          {
  544.             ErrorManager::Instance()->ReportError(ErrorManager::High, 5000, "Temp::Temp", "Write operation failed.");
  545.             throw;
  546.          }
  547.       }
  548.       catch (...)
  549.       {
  550.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5329, "TCPConnection::Write", "An unknown error occurred while writing buffer.");
  551.          throw;
  552.       }
  553.  
  554.    }
  555.  
  556.    void
  557.    TCPConnection::Shutdown(boost::asio::socket_base::shutdown_type what, bool removeFromQueue)
  558.    {
  559.       try
  560.       {
  561.           LOG_DEBUG("TCPConnection::Shutdown");
  562.          // Remove the item we have just handled.
  563.          if (removeFromQueue)
  564.             _operationQueue.Pop(IOOperation::BCTShutdownSend);
  565.  
  566.          try
  567.          {
  568.             GetSocket().shutdown(what);
  569.          }
  570.          catch (boost::system::system_error)
  571.          {
  572.             // hopefully should not matter.
  573.          }
  574.  
  575.  
  576.          _ProcessOperationQueue();
  577.       }
  578.       catch (...)
  579.       {
  580.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5330, "TCPConnection::Shutdown", "An unknown error occurred while shutting down socket.");
  581.          throw;
  582.       }
  583.  
  584.    }
  585.  
  586.    void
  587.    TCPConnection::PostRead(const AnsiString &delimitor)
  588.    {
  589.        LOG_DEBUG("TCPConnection::PostRead");
  590.        try
  591.       {
  592.          shared_ptr<IOOperation> operation = shared_ptr<IOOperation>(new IOOperation(IOOperation::BCTReceive, delimitor));
  593.          _operationQueue.Push(operation);
  594.  
  595.          _ProcessOperationQueue();
  596.       }
  597.       catch (...)
  598.       {
  599.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5331, "TCPConnection::PostRead", "An unknown error occurred while posting read buffer.");
  600.          throw;
  601.       }
  602.    }
  603.  
  604.    void
  605.    TCPConnection::Read(const AnsiString &delimitor)
  606.    {
  607.       try
  608.       {
  609.           // boost is still working on getting the data, so we just bail out.
  610.           if ((_useSSL == true) && (startTLS==false) && (_handshakeDone == false)) return;
  611.          function<void (const boost::system::error_code&, size_t)> handleReadFunction =
  612.             boost::bind(&TCPConnection::HandleRead, shared_from_this(),
  613.             boost::asio::placeholders::error,
  614.             boost::asio::placeholders::bytes_transferred);
  615.  
  616.          try
  617.          {
  618.             if (_useSSL)
  619.             {
  620.                 if (startTLS == true){
  621.                     if (delimitor.GetLength() == 0){
  622.                         LOG_DEBUG("TCPConnection::Read Alternate1");
  623.                       boost::asio::async_read(_sslSocket.next_layer(), _receiveBuffer, boost::asio::transfer_at_least(1), handleReadFunction);
  624.                     }else{
  625.                        LOG_DEBUG("TCPConnection::Read alternate2");
  626.                       boost::asio::async_read_until(_sslSocket.next_layer(), _receiveBuffer,  delimitor, handleReadFunction);
  627.                     }
  628.                 } else {
  629.                     if (delimitor.GetLength() == 0){
  630.                        LOG_DEBUG("TCPConnection::Read SSL normal1");
  631.                       boost::asio::async_read(_sslSocket, _receiveBuffer, boost::asio::transfer_at_least(1), handleReadFunction);
  632.                     }else{
  633.                        LOG_DEBUG("TCPConnection::Read SSL normal2");
  634.                       boost::asio::async_read_until(_sslSocket, _receiveBuffer,  delimitor, handleReadFunction);
  635.                     }
  636.                 }
  637.             }
  638.             else
  639.             {
  640.                 LOG_DEBUG("TCPConnection::Read NON-SSL");
  641.                if (delimitor.GetLength() == 0)
  642.                   boost::asio::async_read(_socket, _receiveBuffer, boost::asio::transfer_at_least(1), handleReadFunction);
  643.                else
  644.                   boost::asio::async_read_until(_socket, _receiveBuffer, delimitor, handleReadFunction);
  645.             }
  646.  
  647.             UpdateLogoutTimer();
  648.          }
  649.          catch (boost::system::system_error error)
  650.          {
  651.             // We failed to send the data to the client. Log an message in the log,
  652.             // and switch of operation-in-progress flag. We don't log this as an
  653.             // error since it most likely isn't.
  654.             String sMessage;
  655.             sMessage.Format(_T("TCPConnection - Receiving of data from client failed. Error code: %d, Message: %s, Remote IP: %s"), error.code().value(), String(error.what()), SafeGetIPAddress());
  656.             LOG_TCPIP(sMessage);
  657.          }
  658.          catch (std::exception const& e)
  659.          {
  660.             String sErrorMessage = Formatter::Format("Read operation failed. Error: {0}", e.what());
  661.             ErrorManager::Instance()->ReportError(ErrorManager::High, 4208, "Temp::Temp", sErrorMessage);
  662.          }
  663.          catch (...)
  664.          {
  665.             ErrorManager::Instance()->ReportError(ErrorManager::High, 5000, "Temp::Temp", "Read operation failed.");
  666.             throw;
  667.          }
  668.       }
  669.       catch (...)
  670.       {
  671.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5332, "TCPConnection::Read", "An unknown error occurred while starting async reading.");
  672.          throw;
  673.       }
  674.    }
  675.  
  676.    void
  677.    TCPConnection::UpdateLogoutTimer()
  678.    {
  679.       try
  680.       {
  681.          // Put a timeout...
  682.          int timeout = _protocolParser->GetTimeout();
  683.          _timer.expires_from_now(boost::posix_time::seconds(timeout));
  684.          _timer.async_wait(bind(&TCPConnection::OnTimeout,
  685.             boost::weak_ptr<TCPConnection>(shared_from_this()), _1));
  686.       }
  687.       catch (...)
  688.       {
  689.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5333, "TCPConnection::UpdateLogoutTimer", "An unknown error occurred while updating logout timer.");
  690.          throw;
  691.       }
  692.    }
  693.  
  694.    void
  695.    TCPConnection::CancelLogoutTimer()
  696.    {
  697.       try
  698.       {
  699.          _timer.cancel();
  700.       }
  701.       catch (boost::system::system_error error)
  702.       {
  703.          ReportError(ErrorManager::Low, 5211, "TCPConnection::CancelLogoutTimer", "Failed to logout timer", error);
  704.       }
  705.       catch (...)
  706.       {
  707.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5334, "TCPConnection::CancelLogoutTimer", "An unknown error occurred while canceling logout timer.");
  708.          throw;
  709.       }
  710.      
  711.    }
  712.  
  713.    void
  714.    TCPConnection::PostDisconnect()
  715.    {
  716.        LOG_DEBUG("TCPConnection::PostDisconnect()");
  717.       try
  718.       {
  719.          shared_ptr<ByteBuffer> pBuf;
  720.          shared_ptr<IOOperation> operation = shared_ptr<IOOperation>(new IOOperation(IOOperation::BCTDisconnect, pBuf));
  721.          _operationQueue.Push(operation);
  722.  
  723.          _ProcessOperationQueue();
  724.       }
  725.       catch (...)
  726.       {
  727.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5335, "TCPConnection::PostDisconnect", "An unknown error occurred while posting disconnect.");
  728.          throw;
  729.       }
  730.    }
  731.  
  732.    void
  733.    TCPConnection::Disconnect()
  734.    {
  735.       try
  736.       {
  737.          LOG_DEBUG("Closing TCP/IP socket");
  738.  
  739.          Shutdown(boost::asio::socket_base::shutdown_both, false);
  740.  
  741.          try
  742.          {
  743.             GetSocket().close();
  744.          }
  745.          catch (boost::system::system_error error)
  746.          {
  747.             // We failed to send the data to the client. Log an message in the log,
  748.             // and switch of operation-in-progress flag. We don't log this as an
  749.             // error since it most likely isn't.
  750.             String sMessage;
  751.             sMessage.Format(_T("TCPConnection - Closing of socket failed. Error code: %d, Message: %s"), error.code().value(), String(error.what()));
  752.             LOG_TCPIP(sMessage);
  753.          }
  754.          catch (...)
  755.          {
  756.             LOG_DEBUG("GetSocket().close() threw");
  757.             // Eat the exception. Not immediately critical.
  758.          }
  759.       }
  760.       catch (...)
  761.       {
  762.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5336, "TCPConnection::Disconnect", "An unknown error occurred while disconnecting.");
  763.          throw;
  764.       }
  765.  
  766.    }
  767.  
  768.    void
  769.    TCPConnection::OnTimeout(boost::weak_ptr<TCPConnection> connection, boost::system::error_code const& err)
  770.    {
  771.       try
  772.       {
  773.          boost::shared_ptr<TCPConnection> conn = connection.lock();
  774.          if (!conn)
  775.          {
  776.             return;
  777.          }
  778.  
  779.          if (err == asio::error::operation_aborted)
  780.          {
  781.             // the timeout operation was cancelled.
  782.             return;
  783.          }
  784.  
  785.          String message;
  786.          message.Format(_T("The client has timed out. Session: %d"), conn->GetSessionID());
  787.          LOG_DEBUG(message);
  788.  
  789.          conn->PostTimeout();
  790.       }
  791.       catch (...)
  792.       {
  793.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5337, "TCPConnection::OnTimeout", "An unknown error occurred while handling timeout.");
  794.          throw;
  795.       }
  796.    }
  797.  
  798.    void
  799.    TCPConnection::PostTimeout()
  800.    {
  801.       try
  802.       {
  803.          if (_hasTimeout)
  804.          {
  805.             // We've already posted a timeout once. Disconnect now.
  806.             Disconnect();
  807.             return;
  808.          }
  809.  
  810.          _hasTimeout = true;
  811.  
  812.          _protocolParser->OnConnectionTimeout();
  813.  
  814.          PostDisconnect();
  815.       }
  816.       catch (boost::system::system_error error)
  817.       {
  818.          ReportError(ErrorManager::Low, 5137, "TCPConnection::PostTimeout", "An error occured while sending a timeout message to the client.", error);
  819.       }
  820.       catch (...)
  821.       {
  822.          ReportError(ErrorManager::Low, 5137, "TCPConnection::PostTimeout", "An error occured while sending a timeout message to the client.");
  823.       }
  824.    }
  825.  
  826.    void
  827.    TCPConnection::PostShutdown(ShutdownOption what)
  828.    {
  829.        LOG_DEBUG("TCPConnection::PostShudown");
  830.       try
  831.       {
  832.          switch (what)
  833.          {
  834.          case TCPConnection::ShutdownSend:
  835.             {
  836.                shared_ptr<ByteBuffer> pBuf;
  837.                shared_ptr<IOOperation> operation = shared_ptr<IOOperation>(new IOOperation(IOOperation::BCTShutdownSend, pBuf));
  838.                _operationQueue.Push(operation);
  839.  
  840.                _ProcessOperationQueue();
  841.             }
  842.            
  843.            break;
  844.          }
  845.       }
  846.       catch (...)
  847.       {
  848.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5338, "TCPConnection::PostShutdown", "An unknown error occurred while posting shutdown.");
  849.          throw;
  850.       }
  851.    }
  852.  
  853.    void
  854.    TCPConnection::HandleRead(const boost::system::error_code& error,  size_t bytes_transferred)
  855.    {
  856.        LOG_DEBUG("TCPConnection::HandleRead");
  857.       try
  858.       {
  859.          // Remove the item we have just handled.
  860.          try
  861.          {
  862.             _operationQueue.Pop(IOOperation::BCTReceive);
  863.          }
  864.          catch (...)
  865.          {
  866.             ReportError(ErrorManager::Medium, 5141, "TCPConnection::HandleRead", "An error occurred while popping queue");
  867.             throw;
  868.          }
  869.  
  870.          try
  871.          {
  872.             if (error.value() != 0)
  873.             {
  874.                // This isn't really an error.
  875.                bool isClientDisconnectedError = error.value() == 2;
  876.                
  877.                if (isClientDisconnectedError == false)
  878.                {
  879.                   _protocolParser->OnReadError(error.value());
  880.  
  881.                   String message;
  882.                   message.Format(_T("The read operation failed. Bytes transferred: %d"), bytes_transferred);
  883.                   ReportDebugMessage(message, error);
  884.                }
  885.  
  886.                if (error.value() == boost::asio::error::not_found)
  887.                {
  888.                    LOG_DEBUG("boost::asio::error::not_found");
  889.                    // read buffer is full...
  890.                   _protocolParser->OnExcessiveDataReceived();
  891.                   PostDisconnect();
  892.                   return;
  893.                }
  894.  
  895.                return;
  896.             }
  897.          }
  898.          catch (...)
  899.          {
  900.             ReportError(ErrorManager::Medium, 5141, "TCPConnection::HandleRead", "An error occurred while checking error state");
  901.             throw;
  902.          }
  903.  
  904.          // Disable the logout timer while we're parsing data. We don't want to terminate
  905.          // a client just because he has issued a long-running command. If we do this, we
  906.          // would have to take care of the fact that we're dropping a connectio despite it
  907.          // still being active.
  908.          try
  909.          {
  910.             CancelLogoutTimer();
  911.          }
  912.          catch (...)
  913.          {
  914.             ReportError(ErrorManager::Medium, 5141, "TCPConnection::HandleRead", "An error occurred while cancelling logout timer.");
  915.             throw;
  916.          }
  917.  
  918.          if (_receiveBinary)
  919.          {
  920.             try
  921.             {
  922.                shared_ptr<ByteBuffer> pBuffer = shared_ptr<ByteBuffer>(new ByteBuffer());
  923.                pBuffer->Allocate(_receiveBuffer.size());
  924.  
  925.                std::istream is(&_receiveBuffer);
  926.                is.read((char*) pBuffer->GetBuffer(), _receiveBuffer.size());
  927.  
  928.                try
  929.                {
  930.                   _protocolParser->ParseData(pBuffer);
  931.                }
  932.                catch (boost::system::system_error error)
  933.                {
  934.                   ReportError(ErrorManager::Medium, 5136, "TCPConnection::HandleRead", "An error occured while parsing buffer.", error);
  935.                   throw;
  936.                }
  937.                catch (...)
  938.                {
  939.                   String message;
  940.                   message.Format(_T("An error occured while parsing buffer. Received bytes: %d, Buffer: %d, Buffer size: %d"), bytes_transferred, &pBuffer, pBuffer->GetSize());
  941.  
  942.                   ReportError(ErrorManager::Medium, 5136, "TCPConnection::HandleRead", "An error occured while parsing buffer.");
  943.                   throw;
  944.                }
  945.             }
  946.             catch (...)
  947.             {
  948.                ReportError(ErrorManager::Medium, 5136, "TCPConnection::HandleRead", "An error occured while parsing binary data.");
  949.                throw;
  950.             }
  951.          }
  952.          else
  953.          {
  954.             std::string s;
  955.             std::istream is(&_receiveBuffer);
  956.             std::getline(is, s, '\r');
  957.  
  958.             // consume trailing \n on line.
  959.             _receiveBuffer.consume(1);
  960.  
  961.       #ifdef _DEBUG
  962.             String sDebugOutput;
  963.             sDebugOutput.Format(_T("RECEIVED: %s\r\n"), String(s));
  964.             OutputDebugString(sDebugOutput);
  965.       #endif
  966.  
  967.             try
  968.             {
  969.                _protocolParser->ParseData(s);
  970.             }
  971.             catch (boost::system::system_error error)
  972.             {
  973.                String message;
  974.                message.Format(_T("An error occured while parsing data. Bytes transferred: %d, ")
  975.                                _T("Data length: %d, Data: %s."),
  976.                                bytes_transferred,
  977.                                s.size(),
  978.                                String(s));
  979.  
  980.                ReportError(ErrorManager::Medium, 5136, "TCPConnection::HandleRead", message, error);
  981.             }
  982.             catch (...)
  983.             {
  984.                String message;
  985.                message.Format(_T("An error occured while parsing data. Data length: %d, Data: %s."), s.size(), String(s));
  986.  
  987.                ReportError(ErrorManager::Medium, 5136, "TCPConnection::HandleRead", message);
  988.             }
  989.          }
  990.       }
  991.       catch (...)
  992.       {
  993.          ReportError(ErrorManager::Medium, 5141, "TCPConnection::HandleRead", "An error occurred while handling read operation.");
  994.          throw;
  995.       }
  996.      
  997.       _ProcessOperationQueue();
  998.    }
  999.  
  1000.    void
  1001.    TCPConnection::HandleWrite(const boost::system::error_code& error,  size_t bytes_transferred)
  1002.    {
  1003.        LOG_DEBUG("TCPConnection::HandleWrite");
  1004.       try
  1005.       {
  1006.          // Remove the item we have just handled.
  1007.          try
  1008.          {
  1009.             _operationQueue.Pop(IOOperation::BCTSend);
  1010.          }
  1011.          catch (...)
  1012.          {
  1013.             ErrorManager::Instance()->ReportError(ErrorManager::High, 5339, "TCPConnection::HandleWrite", "An unknown error occurred while handling buffer write and popping queue.");
  1014.             throw;
  1015.          }
  1016.  
  1017.          if (error.value() != 0)
  1018.          {
  1019.             ReportDebugMessage("The write operation failed.", error);
  1020.             return;
  1021.          }
  1022.  
  1023.          bool containsQueuedSendOperations = false;
  1024.  
  1025.          try
  1026.          {
  1027.             containsQueuedSendOperations = _operationQueue.ContainsQueuedSendOperation();
  1028.          }
  1029.          catch (...)
  1030.          {
  1031.             ErrorManager::Instance()->ReportError(ErrorManager::High, 5339, "TCPConnection::HandleWrite", "An unknown error occurred while handling buffer write and checking if queue contained buffered operations.");
  1032.             throw;
  1033.          }
  1034.  
  1035.          if (!containsQueuedSendOperations)
  1036.          {
  1037.             try
  1038.             {
  1039.                _protocolParser->OnDataSent();
  1040.             }
  1041.             catch (...)
  1042.             {
  1043.                ErrorManager::Instance()->ReportError(ErrorManager::High, 5339, "TCPConnection::HandleWrite", "An unknown error occurred while handling buffer write and notifying protocol parser that data was sent.");
  1044.                throw;
  1045.             }
  1046.  
  1047.          }
  1048.  
  1049.          try
  1050.          {
  1051.             _ProcessOperationQueue();
  1052.          }
  1053.          catch (...)
  1054.          {
  1055.             ErrorManager::Instance()->ReportError(ErrorManager::High, 5339, "TCPConnection::HandleWrite", "An unknown error occurred while handling buffer write and processing the queue.");
  1056.             throw;
  1057.          }
  1058.       }
  1059.       catch (...)
  1060.       {
  1061.          String message;
  1062.          message.Format(_T("An unknown error occurred while handling buffer write. Session ID: %d, Transferred bytes: %d"),  GetSessionID(), bytes_transferred);
  1063.  
  1064.          ErrorManager::Instance()->ReportError(ErrorManager::High, 5339, "TCPConnection::HandleWrite", message);
  1065.          throw;
  1066.       }
  1067.    }
  1068.  
  1069.    IPAddress
  1070.    TCPConnection::GetRemoteEndpointAddress()
  1071.    {
  1072.       boost::asio::ip::tcp::endpoint remoteEndpoint = GetSocket().remote_endpoint();
  1073.       return IPAddress(remoteEndpoint.address());
  1074.    }
  1075.  
  1076.    unsigned long
  1077.    TCPConnection::GetRemoteEndpointPort()
  1078.    {
  1079.       boost::asio::ip::tcp::endpoint remoteEndpoint = GetSocket().remote_endpoint();
  1080.       unsigned long port = remoteEndpoint.port();
  1081.       return port;
  1082.    }
  1083.  
  1084.  
  1085.    unsigned long
  1086.    TCPConnection::GetLocalEndpointPort()
  1087.    {
  1088.       boost::asio::ip::tcp::endpoint localEndpoint = GetSocket().local_endpoint();
  1089.  
  1090.       return localEndpoint.port();
  1091.  
  1092.    }
  1093.  
  1094.    void
  1095.    TCPConnection::SetReceiveBinary(bool binary)
  1096.    {
  1097.       _receiveBinary = binary;
  1098.    }
  1099.  
  1100.    String
  1101.    TCPConnection::SafeGetIPAddress()
  1102.    {
  1103.       try
  1104.       {
  1105.          IPAddress address = GetSocket().remote_endpoint().address();
  1106.  
  1107.          return address.ToString();
  1108.       }
  1109.       catch (...)
  1110.       {
  1111.          return "";
  1112.       }
  1113.    }
  1114.  
  1115.    bool
  1116.    TCPConnection::IsClient()
  1117.    {
  1118.       return _remoteServer.GetLength() > 0;
  1119.    }
  1120.  
  1121.    bool
  1122.    TCPConnection::PrepareSSLContext(boost::asio::ssl::context &ctx)
  1123.    {
  1124.        LOG_DEBUG("TCPConnection::PrepareSSLContext");
  1125.       boost::system::error_code errorCode;
  1126.       ctx.set_options(boost::asio::ssl::context::default_workarounds |
  1127.                              boost::asio::ssl::context::no_sslv2);
  1128.  
  1129.       if (errorCode.value() != 0)
  1130.       {
  1131.          String errorMessage;
  1132.          errorMessage.Format(_T("Failed to set default workarounds."));
  1133.          ReportInitError(ErrorManager::Medium, 5144, "TCPConnection::PrepareContext", errorMessage, errorCode);
  1134.  
  1135.          return false;
  1136.       }
  1137.  
  1138.       if (IniFileSettings::Instance()->GetUseSSLVerifyPeer())
  1139.       {
  1140.          ctx.set_verify_mode(boost::asio::ssl::context::verify_peer | boost::asio::ssl::context::verify_fail_if_no_peer_cert, errorCode);
  1141.          if (errorCode.value() != 0)
  1142.          {
  1143.             String errorMessage;
  1144.             errorMessage.Format(_T("Failed to enable peer verification."));
  1145.             ReportInitError(ErrorManager::Medium, 5144, "TCPConnection::PrepareContext", errorMessage, errorCode);
  1146.  
  1147.             return false;
  1148.          }
  1149.  
  1150.          ctx.add_verify_path(AnsiString(IniFileSettings::Instance()->GetCertificateAuthorityDirectory()), errorCode);
  1151.          if (errorCode.value() != 0)
  1152.          {
  1153.             String errorMessage;
  1154.             errorMessage.Format(_T("Failed to add path to Certificate Authority files."));
  1155.             ReportInitError(ErrorManager::Medium, 5144, "TCPConnection::PrepareContext", errorMessage, errorCode);
  1156.             return false;
  1157.          }
  1158.       }      
  1159.  
  1160.       return true;
  1161.    }
  1162.  
  1163.    void  
  1164.    TCPConnection::SetSecurityRange(shared_ptr<SecurityRange> securityRange)
  1165.    {
  1166.       _securityRange = securityRange;
  1167.    }
  1168.  
  1169.    shared_ptr<SecurityRange>
  1170.    TCPConnection::GetSecurityRange()
  1171.    {
  1172.       if (!_securityRange)
  1173.       {
  1174.          IPAddress address(GetSocket().remote_endpoint().address());
  1175.  
  1176.          _securityRange = PersistentSecurityRange::ReadMatchingIP(address);
  1177.       }
  1178.  
  1179.       return _securityRange;
  1180.    }
  1181.  
  1182.    shared_ptr<TCPConnection>
  1183.    TCPConnection::GetSharedFromThis()
  1184.    {
  1185.       return shared_from_this();
  1186.    }
  1187.  
  1188.    int
  1189.    TCPConnection::GetSessionID()
  1190.    {
  1191.       try
  1192.       {
  1193.          int sessionID = _protocolParser->GetSessionID();
  1194.          return sessionID;
  1195.       }
  1196.       catch (...)
  1197.       {
  1198.          return 0;
  1199.       }
  1200.    }
  1201. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement