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 <osl/security.hxx> 21 #include "acceptor.hxx" 22 #include <com/sun/star/connection/XConnection.hpp> 23 #include <com/sun/star/connection/ConnectionSetupException.hpp> 24 #include <com/sun/star/io/IOException.hpp> 25 26 #include <osl/diagnose.h> 27 #include <osl/mutex.hxx> 28 #include <cppuhelper/implbase.hxx> 29 #include <rtl/ref.hxx> 30 31 using namespace ::osl; 32 using namespace ::cppu; 33 using namespace ::com::sun::star::uno; 34 using namespace ::com::sun::star::lang; 35 using namespace ::com::sun::star::connection; 36 using namespace ::com::sun::star::io; 37 38 39 namespace io_acceptor 40 { 41 namespace { 42 43 class PipeConnection : 44 public WeakImplHelper< XConnection > 45 { 46 public: 47 explicit PipeConnection( const OUString &sConnectionDescription); 48 49 virtual sal_Int32 SAL_CALL read( Sequence< sal_Int8 >& aReadBytes, sal_Int32 nBytesToRead ) override; 50 virtual void SAL_CALL write( const Sequence< sal_Int8 >& aData ) override; 51 virtual void SAL_CALL flush( ) override; 52 virtual void SAL_CALL close( ) override; 53 virtual OUString SAL_CALL getDescription( ) override; 54 public: 55 ::osl::StreamPipe m_pipe; 56 oslInterlockedCount m_nStatus; 57 OUString m_sDescription; 58 }; 59 60 } 61 PipeConnection(const OUString & sConnectionDescription)62 PipeConnection::PipeConnection( const OUString &sConnectionDescription) : 63 m_nStatus( 0 ), 64 m_sDescription( sConnectionDescription ) 65 { 66 // make it unique 67 m_sDescription += ",uniqueValue="; 68 m_sDescription += OUString::number( 69 sal::static_int_cast<sal_Int64 >( 70 reinterpret_cast< sal_IntPtr >(&m_pipe)) ); 71 } 72 read(Sequence<sal_Int8> & aReadBytes,sal_Int32 nBytesToRead)73 sal_Int32 PipeConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead ) 74 { 75 if( m_nStatus ) 76 { 77 throw IOException("pipe already closed"); 78 } 79 if( aReadBytes.getLength() < nBytesToRead ) 80 { 81 aReadBytes.realloc( nBytesToRead ); 82 } 83 sal_Int32 n = m_pipe.read( aReadBytes.getArray(), nBytesToRead ); 84 OSL_ASSERT( n >= 0 && n <= aReadBytes.getLength() ); 85 if( n < aReadBytes.getLength() ) 86 { 87 aReadBytes.realloc( n ); 88 } 89 return n; 90 91 } 92 write(const Sequence<sal_Int8> & seq)93 void PipeConnection::write( const Sequence < sal_Int8 > &seq ) 94 { 95 if( m_nStatus ) 96 { 97 throw IOException("pipe already closed"); 98 } 99 if( m_pipe.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() ) 100 { 101 throw IOException("short write"); 102 } 103 } 104 flush()105 void PipeConnection::flush( ) 106 { 107 } 108 close()109 void PipeConnection::close() 110 { 111 if( 1 == osl_atomic_increment( (&m_nStatus) ) ) 112 { 113 m_pipe.close(); 114 } 115 } 116 getDescription()117 OUString PipeConnection::getDescription() 118 { 119 return m_sDescription; 120 } 121 122 /*************** 123 * PipeAcceptor 124 **************/ PipeAcceptor(const OUString & sPipeName,const OUString & sConnectionDescription)125 PipeAcceptor::PipeAcceptor( const OUString &sPipeName , const OUString & sConnectionDescription) : 126 m_sPipeName( sPipeName ), 127 m_sConnectionDescription( sConnectionDescription ), 128 m_bClosed( false ) 129 { 130 } 131 132 init()133 void PipeAcceptor::init() 134 { 135 m_pipe = Pipe( m_sPipeName.pData , osl_Pipe_CREATE , osl::Security() ); 136 if( ! m_pipe.is() ) 137 { 138 OUString error = "io.acceptor: Couldn't setup pipe " + m_sPipeName; 139 throw ConnectionSetupException( error ); 140 } 141 } 142 accept()143 Reference< XConnection > PipeAcceptor::accept( ) 144 { 145 Pipe pipe; 146 { 147 MutexGuard guard( m_mutex ); 148 pipe = m_pipe; 149 } 150 if( ! pipe.is() ) 151 { 152 OUString error = "io.acceptor: pipe already closed" + m_sPipeName; 153 throw ConnectionSetupException( error ); 154 } 155 rtl::Reference<PipeConnection> pConn(new PipeConnection( m_sConnectionDescription )); 156 157 oslPipeError status = pipe.accept( pConn->m_pipe ); 158 159 if( m_bClosed ) 160 { 161 // stopAccepting was called ! 162 return Reference < XConnection >(); 163 } 164 else if( osl_Pipe_E_None == status ) 165 { 166 return pConn; 167 } 168 else 169 { 170 OUString error = "io.acceptor: Couldn't setup pipe " + m_sPipeName; 171 throw ConnectionSetupException( error ); 172 } 173 } 174 stopAccepting()175 void PipeAcceptor::stopAccepting() 176 { 177 m_bClosed = true; 178 Pipe pipe; 179 { 180 MutexGuard guard( m_mutex ); 181 pipe = m_pipe; 182 m_pipe.clear(); 183 } 184 if( pipe.is() ) 185 { 186 pipe.close(); 187 } 188 } 189 } 190 191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 192