1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_io.hxx" 30 31 #include "connector.hxx" 32 #include <rtl/ustrbuf.hxx> 33 #include <algorithm> 34 35 using namespace ::osl; 36 using namespace ::rtl; 37 using namespace ::com::sun::star::uno; 38 using namespace ::com::sun::star::io; 39 using namespace ::com::sun::star::connection; 40 41 42 namespace stoc_connector { 43 template<class T> 44 void notifyListeners(SocketConnection * pCon, sal_Bool * notified, T t) 45 { 46 XStreamListener_hash_set listeners; 47 48 { 49 ::osl::MutexGuard guard(pCon->_mutex); 50 if(!*notified) 51 { 52 *notified = sal_True; 53 listeners = pCon->_listeners; 54 } 55 } 56 57 ::std::for_each(listeners.begin(), listeners.end(), t); 58 } 59 60 61 static void callStarted(Reference<XStreamListener> xStreamListener) 62 { 63 xStreamListener->started(); 64 } 65 66 struct callError { 67 const Any & any; 68 69 callError(const Any & any); 70 71 void operator () (Reference<XStreamListener> xStreamListener); 72 }; 73 74 callError::callError(const Any & aAny) 75 : any(aAny) 76 { 77 } 78 79 void callError::operator () (Reference<XStreamListener> xStreamListener) 80 { 81 xStreamListener->error(any); 82 } 83 84 static void callClosed(Reference<XStreamListener> xStreamListener) 85 { 86 xStreamListener->closed(); 87 } 88 89 90 SocketConnection::SocketConnection( const OUString &sConnectionDescription ) : 91 m_nStatus( 0 ), 92 m_sDescription( sConnectionDescription ), 93 _started(sal_False), 94 _closed(sal_False), 95 _error(sal_False) 96 { 97 // make it unique 98 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 99 m_sDescription += OUString( RTL_CONSTASCII_USTRINGPARAM( ",uniqueValue=" ) ); 100 m_sDescription += OUString::valueOf( 101 sal::static_int_cast< sal_Int64 >( 102 reinterpret_cast< sal_IntPtr >(&m_socket)), 103 10 ); 104 } 105 106 SocketConnection::~SocketConnection() 107 { 108 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 109 } 110 111 void SocketConnection::completeConnectionString() 112 { 113 sal_Int32 nPort; 114 115 nPort = m_socket.getPeerPort(); 116 117 OUStringBuffer buf( 256 ); 118 buf.appendAscii( ",peerPort=" ); 119 buf.append( (sal_Int32) nPort ); 120 buf.appendAscii( ",peerHost=" ); 121 buf.append( m_socket.getPeerHost() ); 122 123 buf.appendAscii( ",localPort=" ); 124 buf.append( (sal_Int32) nPort ); 125 buf.appendAscii( ",localHost=" ); 126 buf.append( m_socket.getLocalHost( ) ); 127 128 m_sDescription += buf.makeStringAndClear(); 129 } 130 131 sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead ) 132 throw(::com::sun::star::io::IOException, 133 ::com::sun::star::uno::RuntimeException) 134 { 135 if( ! m_nStatus ) 136 { 137 notifyListeners(this, &_started, callStarted); 138 139 if( aReadBytes.getLength() != nBytesToRead ) 140 { 141 aReadBytes.realloc( nBytesToRead ); 142 } 143 sal_Int32 i = m_socket.read( aReadBytes.getArray() , aReadBytes.getLength() ); 144 145 if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None) 146 { 147 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - ")); 148 message += m_socket.getErrorAsString(); 149 150 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 151 152 Any any; 153 any <<= ioException; 154 155 notifyListeners(this, &_error, callError(any)); 156 157 throw ioException; 158 } 159 160 return i; 161 } 162 else 163 { 164 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - connection already closed")); 165 166 IOException ioException(message, Reference<XInterface>(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 177 void SocketConnection::write( const Sequence < sal_Int8 > &seq ) 178 throw(::com::sun::star::io::IOException, 179 ::com::sun::star::uno::RuntimeException) 180 { 181 if( ! m_nStatus ) 182 { 183 if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() ) 184 { 185 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - ")); 186 message += m_socket.getErrorAsString(); 187 188 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 189 190 Any any; 191 any <<= ioException; 192 193 notifyListeners(this, &_error, callError(any)); 194 195 throw ioException; 196 } 197 } 198 else 199 { 200 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - connection already closed")); 201 202 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 203 204 Any any; 205 any <<= ioException; 206 207 notifyListeners(this, &_error, callError(any)); 208 209 throw ioException; 210 } 211 } 212 213 void SocketConnection::flush( ) 214 throw(::com::sun::star::io::IOException, 215 ::com::sun::star::uno::RuntimeException) 216 { 217 218 } 219 220 void SocketConnection::close() 221 throw(::com::sun::star::io::IOException, 222 ::com::sun::star::uno::RuntimeException) 223 { 224 // ensure that close is called only once 225 if( 1 == osl_incrementInterlockedCount( (&m_nStatus) ) ) 226 { 227 m_socket.shutdown(); 228 notifyListeners(this, &_closed, callClosed); 229 } 230 } 231 232 OUString SocketConnection::getDescription() 233 throw( ::com::sun::star::uno::RuntimeException) 234 { 235 return m_sDescription; 236 } 237 238 239 240 // XConnectionBroadcaster 241 void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException) 242 { 243 MutexGuard guard(_mutex); 244 245 _listeners.insert(aListener); 246 } 247 248 void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException) 249 { 250 MutexGuard guard(_mutex); 251 252 _listeners.erase(aListener); 253 } 254 } 255 256