LCOV - code coverage report
Current view: top level - io/source/acceptor - acc_socket.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 144 0.0 %
Date: 2014-11-03 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "acceptor.hxx"
      21             : 
      22             : #include <boost/unordered_set.hpp>
      23             : #include <algorithm>
      24             : 
      25             : #include <rtl/ustrbuf.hxx>
      26             : #include <com/sun/star/connection/XConnectionBroadcaster.hpp>
      27             : #include <com/sun/star/connection/ConnectionSetupException.hpp>
      28             : 
      29             : #include <cppuhelper/implbase2.hxx>
      30             : 
      31             : using namespace ::osl;
      32             : using namespace ::cppu;
      33             : using namespace ::com::sun::star::uno;
      34             : using namespace ::com::sun::star::io;
      35             : using namespace ::com::sun::star::connection;
      36             : 
      37             : 
      38             : namespace io_acceptor {
      39             :     template<class T>
      40             :     struct ReferenceHash
      41             :     {
      42           0 :         size_t operator () (const ::com::sun::star::uno::Reference<T> & ref) const
      43             :         {
      44           0 :             return (size_t)ref.get();
      45             :         }
      46             :     };
      47             : 
      48             :     template<class T>
      49             :     struct ReferenceEqual
      50             :     {
      51           0 :         bool operator () (const ::com::sun::star::uno::Reference<T> & op1,
      52             :                               const ::com::sun::star::uno::Reference<T> & op2) const
      53             :         {
      54           0 :             return op1.get() == op2.get();
      55             :         }
      56             :     };
      57             : 
      58             : 
      59             :     typedef ::boost::unordered_set< ::com::sun::star::uno::Reference< ::com::sun::star::io::XStreamListener>,
      60             :                              ReferenceHash< ::com::sun::star::io::XStreamListener>,
      61             :                              ReferenceEqual< ::com::sun::star::io::XStreamListener> >
      62             :             XStreamListener_hash_set;
      63             : 
      64             : 
      65             :     class SocketConnection : public ::cppu::WeakImplHelper2<
      66             :         ::com::sun::star::connection::XConnection,
      67             :         ::com::sun::star::connection::XConnectionBroadcaster>
      68             : 
      69             :     {
      70             :     public:
      71             :         SocketConnection( const OUString & sConnectionDescription );
      72             :         virtual ~SocketConnection();
      73             : 
      74             :         virtual sal_Int32 SAL_CALL read( ::com::sun::star::uno::Sequence< sal_Int8 >& aReadBytes,
      75             :                                          sal_Int32 nBytesToRead )
      76             :             throw(::com::sun::star::io::IOException,
      77             :                   ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      78             :         virtual void SAL_CALL write( const ::com::sun::star::uno::Sequence< sal_Int8 >& aData )
      79             :             throw(::com::sun::star::io::IOException,
      80             :                   ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      81             :         virtual void SAL_CALL flush(  ) throw(
      82             :             ::com::sun::star::io::IOException,
      83             :             ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      84             :         virtual void SAL_CALL close(  )
      85             :             throw(::com::sun::star::io::IOException,
      86             :                   ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      87             :         virtual OUString SAL_CALL getDescription(  )
      88             :             throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      89             : 
      90             :         // XConnectionBroadcaster
      91             :         virtual void SAL_CALL addStreamListener(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStreamListener>& aListener)
      92             :             throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      93             :         virtual void SAL_CALL removeStreamListener(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XStreamListener>& aListener)
      94             :             throw(::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
      95             : 
      96             :     public:
      97             :         void completeConnectionString();
      98             : 
      99             :         ::osl::StreamSocket m_socket;
     100             :         ::osl::SocketAddr m_addr;
     101             :         oslInterlockedCount m_nStatus;
     102             :         OUString m_sDescription;
     103             : 
     104             :         ::osl::Mutex _mutex;
     105             :         bool     _started;
     106             :         bool     _closed;
     107             :         bool     _error;
     108             :         XStreamListener_hash_set _listeners;
     109             :     };
     110             : 
     111             :     template<class T>
     112           0 :     void notifyListeners(SocketConnection * pCon, bool * notified, T t)
     113             :     {
     114           0 :           XStreamListener_hash_set listeners;
     115             : 
     116             :         {
     117           0 :             ::osl::MutexGuard guard(pCon->_mutex);
     118           0 :             if(!*notified)
     119             :             {
     120           0 :                 *notified = true;
     121           0 :                 listeners = pCon->_listeners;
     122           0 :             }
     123             :         }
     124             : 
     125           0 :         ::std::for_each(listeners.begin(), listeners.end(), t);
     126           0 :     }
     127             : 
     128           0 :     static void callStarted(Reference<XStreamListener> xStreamListener)
     129             :     {
     130           0 :         xStreamListener->started();
     131           0 :     }
     132             : 
     133             :     struct callError {
     134             :         const Any & any;
     135             : 
     136             :         callError(const Any & any);
     137             : 
     138             :         void operator () (Reference<XStreamListener> xStreamListener);
     139             :     };
     140             : 
     141           0 :     callError::callError(const Any & aAny)
     142           0 :         : any(aAny)
     143             :     {
     144           0 :     }
     145             : 
     146           0 :     void callError::operator () (Reference<XStreamListener> xStreamListener)
     147             :     {
     148           0 :         xStreamListener->error(any);
     149           0 :     }
     150             : 
     151           0 :     static void callClosed(Reference<XStreamListener> xStreamListener)
     152             :     {
     153           0 :         xStreamListener->closed();
     154           0 :     }
     155             : 
     156             : 
     157           0 :     SocketConnection::SocketConnection( const OUString &sConnectionDescription) :
     158             :         m_nStatus( 0 ),
     159             :         m_sDescription( sConnectionDescription ),
     160             :         _started(false),
     161             :         _closed(false),
     162           0 :         _error(false)
     163             :     {
     164             :         // make it unique
     165           0 :         m_sDescription += ",uniqueValue=" ;
     166           0 :         m_sDescription += OUString::number(
     167             :             sal::static_int_cast< sal_Int64 >(
     168             :                 reinterpret_cast< sal_IntPtr >(&m_socket)),
     169           0 :             10 );
     170           0 :     }
     171             : 
     172           0 :     SocketConnection::~SocketConnection()
     173             :     {
     174           0 :     }
     175             : 
     176           0 :     void SocketConnection::completeConnectionString()
     177             :     {
     178           0 :         OUStringBuffer buf( 256 );
     179           0 :         buf.appendAscii( ",peerPort=" );
     180           0 :         buf.append( (sal_Int32) m_socket.getPeerPort() );
     181           0 :         buf.appendAscii( ",peerHost=" );
     182           0 :         buf.append( m_socket.getPeerHost( ) );
     183             : 
     184           0 :         buf.appendAscii( ",localPort=" );
     185           0 :         buf.append( (sal_Int32) m_socket.getLocalPort() );
     186           0 :         buf.appendAscii( ",localHost=" );
     187           0 :         buf.append( m_socket.getLocalHost() );
     188             : 
     189           0 :         m_sDescription += buf.makeStringAndClear();
     190           0 :     }
     191             : 
     192           0 :     sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead )
     193             :             throw(::com::sun::star::io::IOException,
     194             :                   ::com::sun::star::uno::RuntimeException, std::exception)
     195             :     {
     196           0 :         if( ! m_nStatus )
     197             :         {
     198           0 :             notifyListeners(this, &_started, callStarted);
     199             : 
     200           0 :             if( aReadBytes.getLength() != nBytesToRead )
     201             :             {
     202           0 :                 aReadBytes.realloc( nBytesToRead );
     203             :             }
     204             : 
     205           0 :             sal_Int32 i = 0;
     206           0 :             i = m_socket.read( aReadBytes.getArray()  , aReadBytes.getLength() );
     207             : 
     208           0 :             if(i != nBytesToRead)
     209             :             {
     210           0 :                 OUString message("acc_socket.cxx:SocketConnection::read: error - ");
     211           0 :                 message +=  m_socket.getErrorAsString();
     212             : 
     213           0 :                 IOException ioException(message, static_cast<XConnection *>(this));
     214             : 
     215           0 :                 Any any;
     216           0 :                 any <<= ioException;
     217             : 
     218           0 :                 notifyListeners(this, &_error, callError(any));
     219             : 
     220           0 :                 throw ioException;
     221             :             }
     222             : 
     223           0 :             return i;
     224             :         }
     225             :         else
     226             :         {
     227           0 :             OUString message("acc_socket.cxx:SocketConnection::read: error - connection already closed");
     228             : 
     229           0 :             IOException ioException(message, static_cast<XConnection *>(this));
     230             : 
     231           0 :             Any any;
     232           0 :             any <<= ioException;
     233             : 
     234           0 :             notifyListeners(this, &_error, callError(any));
     235             : 
     236           0 :             throw ioException;
     237             :         }
     238             :     }
     239             : 
     240           0 :     void SocketConnection::write( const Sequence < sal_Int8 > &seq )
     241             :             throw(::com::sun::star::io::IOException,
     242             :                   ::com::sun::star::uno::RuntimeException, std::exception)
     243             :     {
     244           0 :         if( ! m_nStatus )
     245             :         {
     246           0 :             if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() )
     247             :             {
     248           0 :                 OUString message("acc_socket.cxx:SocketConnection::write: error - ");
     249           0 :                 message += m_socket.getErrorAsString();
     250             : 
     251           0 :                 IOException ioException(message, static_cast<XConnection *>(this));
     252             : 
     253           0 :                 Any any;
     254           0 :                 any <<= ioException;
     255             : 
     256           0 :                 notifyListeners(this, &_error, callError(any));
     257             : 
     258           0 :                 throw ioException;
     259             :             }
     260             :         }
     261             :         else
     262             :         {
     263           0 :             OUString message("acc_socket.cxx:SocketConnection::write: error - connection already closed");
     264             : 
     265           0 :             IOException ioException(message, static_cast<XConnection *>(this));
     266             : 
     267           0 :             Any any;
     268           0 :             any <<= ioException;
     269             : 
     270           0 :             notifyListeners(this, &_error, callError(any));
     271             : 
     272           0 :             throw ioException;
     273             :         }
     274           0 :     }
     275             : 
     276           0 :     void SocketConnection::flush( )
     277             :             throw(::com::sun::star::io::IOException,
     278             :                   ::com::sun::star::uno::RuntimeException, std::exception)
     279             :     {
     280             : 
     281           0 :     }
     282             : 
     283           0 :     void SocketConnection::close()
     284             :             throw(::com::sun::star::io::IOException,
     285             :                   ::com::sun::star::uno::RuntimeException, std::exception)
     286             :     {
     287             :         // ensure close is called only once
     288           0 :         if(  1 == osl_atomic_increment( (&m_nStatus) ) )
     289             :         {
     290           0 :             m_socket.shutdown();
     291           0 :             notifyListeners(this, &_closed, callClosed);
     292             :         }
     293           0 :     }
     294             : 
     295           0 :     OUString SocketConnection::getDescription()
     296             :             throw( ::com::sun::star::uno::RuntimeException, std::exception)
     297             :     {
     298           0 :         return m_sDescription;
     299             :     }
     300             : 
     301             : 
     302             :     // XConnectionBroadcaster
     303           0 :     void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException, std::exception)
     304             :     {
     305           0 :         MutexGuard guard(_mutex);
     306             : 
     307           0 :         _listeners.insert(aListener);
     308           0 :     }
     309             : 
     310           0 :     void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException, std::exception)
     311             :     {
     312           0 :         MutexGuard guard(_mutex);
     313             : 
     314           0 :         _listeners.erase(aListener);
     315           0 :     }
     316             : 
     317           0 :     SocketAcceptor::SocketAcceptor( const OUString &sSocketName,
     318             :                                     sal_uInt16 nPort,
     319             :                                     bool bTcpNoDelay,
     320             :                                     const OUString &sConnectionDescription) :
     321             :         m_sSocketName( sSocketName ),
     322             :         m_sConnectionDescription( sConnectionDescription ),
     323             :         m_nPort( nPort ),
     324             :         m_bTcpNoDelay( bTcpNoDelay ),
     325           0 :         m_bClosed( false )
     326             :     {
     327           0 :     }
     328             : 
     329             : 
     330           0 :     void SocketAcceptor::init()
     331             :     {
     332           0 :         if( ! m_addr.setPort( m_nPort ) )
     333             :         {
     334           0 :             OUStringBuffer message( 128 );
     335           0 :             message.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - invalid tcp/ip port " );
     336           0 :             message.append( (sal_Int32) m_nPort );
     337           0 :             throw ConnectionSetupException( message.makeStringAndClear() );
     338             :         }
     339           0 :         if( ! m_addr.setHostname( m_sSocketName.pData ) )
     340             :         {
     341           0 :             OUStringBuffer message( 128 );
     342           0 :             message.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - invalid host " );
     343           0 :             message.append( m_sSocketName );
     344           0 :             throw ConnectionSetupException( message.makeStringAndClear() );
     345             :         }
     346           0 :         m_socket.setOption( osl_Socket_OptionReuseAddr, 1);
     347             : 
     348           0 :         if(! m_socket.bind(m_addr) )
     349             :         {
     350           0 :             OUStringBuffer message( 128 );
     351           0 :             message.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - couldn't bind on " );
     352           0 :             message.append( m_sSocketName ).appendAscii( ":" ).append((sal_Int32)m_nPort);
     353           0 :             throw ConnectionSetupException( message.makeStringAndClear() );
     354             :         }
     355             : 
     356           0 :         if(! m_socket.listen() )
     357             :         {
     358           0 :             OUStringBuffer message( 128 );
     359           0 :             message.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - can't listen on " );
     360           0 :             message.append( m_sSocketName ).appendAscii( ":" ).append( (sal_Int32) m_nPort);
     361           0 :             throw ConnectionSetupException( message.makeStringAndClear() );
     362             :         }
     363           0 :     }
     364             : 
     365           0 :     Reference< XConnection > SocketAcceptor::accept( )
     366             :     {
     367           0 :         SocketConnection *pConn = new SocketConnection( m_sConnectionDescription );
     368             : 
     369           0 :         if( m_socket.acceptConnection( pConn->m_socket )!= osl_Socket_Ok )
     370             :         {
     371             :             // stopAccepting was called
     372           0 :             delete pConn;
     373           0 :             return Reference < XConnection > ();
     374             :         }
     375           0 :         if( m_bClosed )
     376             :         {
     377           0 :             delete pConn;
     378           0 :             return Reference < XConnection > ();
     379             :         }
     380             : 
     381           0 :         pConn->completeConnectionString();
     382           0 :         if( m_bTcpNoDelay )
     383             :         {
     384           0 :             sal_Int32 nTcpNoDelay = sal_True;
     385             :             pConn->m_socket.setOption( osl_Socket_OptionTcpNoDelay , &nTcpNoDelay,
     386           0 :                                        sizeof( nTcpNoDelay ) , osl_Socket_LevelTcp );
     387             :         }
     388             : 
     389           0 :         return Reference < XConnection > ( (XConnection * ) pConn );
     390             :     }
     391             : 
     392           0 :     void SocketAcceptor::stopAccepting()
     393             :     {
     394           0 :         m_bClosed = true;
     395           0 :         m_socket.close();
     396           0 :     }
     397             : }
     398             : 
     399             : 
     400             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10