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