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 21 #include "connector.hxx" 22 #include <com/sun/star/io/IOException.hpp> 23 #include <rtl/ustrbuf.hxx> 24 25 using namespace ::osl; 26 using namespace ::com::sun::star::uno; 27 using namespace ::com::sun::star::io; 28 using namespace ::com::sun::star::connection; 29 30 31 namespace stoc_connector { 32 template<class T> notifyListeners(SocketConnection * pCon,bool * notified,T t)33 static void notifyListeners(SocketConnection * pCon, bool * notified, T t) 34 { 35 XStreamListener_hash_set listeners; 36 37 { 38 ::osl::MutexGuard guard(pCon->_mutex); 39 if(!*notified) 40 { 41 *notified = true; 42 listeners = pCon->_listeners; 43 } 44 } 45 46 for(auto& listener : listeners) 47 t(listener); 48 } 49 50 callStarted(const Reference<XStreamListener> & xStreamListener)51 static void callStarted(const Reference<XStreamListener>& xStreamListener) 52 { 53 xStreamListener->started(); 54 } 55 56 namespace { 57 58 struct callError { 59 const Any & any; 60 61 explicit callError(const Any & any); 62 63 void operator () (const Reference<XStreamListener>& xStreamListener); 64 }; 65 66 } 67 callError(const Any & aAny)68 callError::callError(const Any & aAny) 69 : any(aAny) 70 { 71 } 72 operator ()(const Reference<XStreamListener> & xStreamListener)73 void callError::operator () (const Reference<XStreamListener>& xStreamListener) 74 { 75 xStreamListener->error(any); 76 } 77 callClosed(const Reference<XStreamListener> & xStreamListener)78 static void callClosed(const Reference<XStreamListener>& xStreamListener) 79 { 80 xStreamListener->closed(); 81 } 82 83 SocketConnection(const OUString & sConnectionDescription)84 SocketConnection::SocketConnection( const OUString &sConnectionDescription ) : 85 m_nStatus( 0 ), 86 m_sDescription( sConnectionDescription ), 87 _started(false), 88 _closed(false), 89 _error(false) 90 { 91 // make it unique 92 m_sDescription += ",uniqueValue="; 93 m_sDescription += OUString::number( 94 sal::static_int_cast< sal_Int64 >( 95 reinterpret_cast< sal_IntPtr >(&m_socket)) ); 96 } 97 ~SocketConnection()98 SocketConnection::~SocketConnection() 99 { 100 } 101 completeConnectionString()102 void SocketConnection::completeConnectionString() 103 { 104 sal_Int32 nPort; 105 106 nPort = m_socket.getPeerPort(); 107 108 m_sDescription += 109 ",peerPort=" + OUString::number( nPort ) + 110 ",peerHost=" + m_socket.getPeerHost() + 111 ",localPort=" + OUString::number( nPort ) + 112 ",localHost=" + m_socket.getLocalHost( ); 113 } 114 read(Sequence<sal_Int8> & aReadBytes,sal_Int32 nBytesToRead)115 sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead ) 116 { 117 if( ! m_nStatus ) 118 { 119 notifyListeners(this, &_started, callStarted); 120 121 if( aReadBytes.getLength() != nBytesToRead ) 122 { 123 aReadBytes.realloc( nBytesToRead ); 124 } 125 sal_Int32 i = m_socket.read( aReadBytes.getArray() , aReadBytes.getLength() ); 126 127 if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None) 128 { 129 OUString message = "ctr_socket.cxx:SocketConnection::read: error - " + 130 m_socket.getErrorAsString(); 131 132 IOException ioException(message, static_cast<XConnection *>(this)); 133 134 Any any; 135 any <<= ioException; 136 137 notifyListeners(this, &_error, callError(any)); 138 139 throw ioException; 140 } 141 142 return i; 143 } 144 else 145 { 146 IOException ioException("ctr_socket.cxx:SocketConnection::read: error - connection already closed", static_cast<XConnection *>(this)); 147 148 Any any; 149 any <<= ioException; 150 151 notifyListeners(this, &_error, callError(any)); 152 153 throw ioException; 154 } 155 } 156 write(const Sequence<sal_Int8> & seq)157 void SocketConnection::write( const Sequence < sal_Int8 > &seq ) 158 { 159 if( ! m_nStatus ) 160 { 161 if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() ) 162 { 163 OUString message = "ctr_socket.cxx:SocketConnection::write: error - " + 164 m_socket.getErrorAsString(); 165 166 IOException ioException(message, static_cast<XConnection *>(this)); 167 168 Any any; 169 any <<= ioException; 170 171 notifyListeners(this, &_error, callError(any)); 172 173 throw ioException; 174 } 175 } 176 else 177 { 178 IOException ioException("ctr_socket.cxx:SocketConnection::write: error - connection already closed", static_cast<XConnection *>(this)); 179 180 Any any; 181 any <<= ioException; 182 183 notifyListeners(this, &_error, callError(any)); 184 185 throw ioException; 186 } 187 } 188 flush()189 void SocketConnection::flush( ) 190 { 191 192 } 193 close()194 void SocketConnection::close() 195 { 196 // ensure that close is called only once 197 if( 1 == osl_atomic_increment( (&m_nStatus) ) ) 198 { 199 m_socket.shutdown(); 200 notifyListeners(this, &_closed, callClosed); 201 } 202 } 203 getDescription()204 OUString SocketConnection::getDescription() 205 { 206 return m_sDescription; 207 } 208 209 210 // XConnectionBroadcaster addStreamListener(const Reference<XStreamListener> & aListener)211 void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener) 212 { 213 MutexGuard guard(_mutex); 214 215 _listeners.insert(aListener); 216 } 217 removeStreamListener(const Reference<XStreamListener> & aListener)218 void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener) 219 { 220 MutexGuard guard(_mutex); 221 222 _listeners.erase(aListener); 223 } 224 } 225 226 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 227