1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_io.hxx" 26 27 #include "connector.hxx" 28 #include <rtl/ustrbuf.hxx> 29 #include <algorithm> 30 31 using namespace ::osl; 32 using namespace ::rtl; 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 stoc_connector { 39 template<class T> notifyListeners(SocketConnection * pCon,sal_Bool * notified,T t)40 void notifyListeners(SocketConnection * pCon, sal_Bool * notified, T t) 41 { 42 XStreamListener_hash_set listeners; 43 44 { 45 ::osl::MutexGuard guard(pCon->_mutex); 46 if(!*notified) 47 { 48 *notified = sal_True; 49 listeners = pCon->_listeners; 50 } 51 } 52 53 ::std::for_each(listeners.begin(), listeners.end(), t); 54 } 55 56 callStarted(Reference<XStreamListener> xStreamListener)57 static void callStarted(Reference<XStreamListener> xStreamListener) 58 { 59 xStreamListener->started(); 60 } 61 62 struct callError { 63 const Any & any; 64 65 callError(const Any & any); 66 67 void operator () (Reference<XStreamListener> xStreamListener); 68 }; 69 callError(const Any & aAny)70 callError::callError(const Any & aAny) 71 : any(aAny) 72 { 73 } 74 operator ()(Reference<XStreamListener> xStreamListener)75 void callError::operator () (Reference<XStreamListener> xStreamListener) 76 { 77 xStreamListener->error(any); 78 } 79 callClosed(Reference<XStreamListener> xStreamListener)80 static void callClosed(Reference<XStreamListener> xStreamListener) 81 { 82 xStreamListener->closed(); 83 } 84 85 SocketConnection(const OUString & sConnectionDescription)86 SocketConnection::SocketConnection( const OUString &sConnectionDescription ) : 87 m_nStatus( 0 ), 88 m_sDescription( sConnectionDescription ), 89 _started(sal_False), 90 _closed(sal_False), 91 _error(sal_False) 92 { 93 // make it unique 94 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); 95 m_sDescription += OUString( RTL_CONSTASCII_USTRINGPARAM( ",uniqueValue=" ) ); 96 m_sDescription += OUString::valueOf( 97 sal::static_int_cast< sal_Int64 >( 98 reinterpret_cast< sal_IntPtr >(&m_socket)), 99 10 ); 100 } 101 ~SocketConnection()102 SocketConnection::~SocketConnection() 103 { 104 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 105 } 106 completeConnectionString()107 void SocketConnection::completeConnectionString() 108 { 109 sal_Int32 nPort; 110 111 nPort = m_socket.getPeerPort(); 112 113 OUStringBuffer buf( 256 ); 114 buf.appendAscii( ",peerPort=" ); 115 buf.append( (sal_Int32) nPort ); 116 buf.appendAscii( ",peerHost=" ); 117 buf.append( m_socket.getPeerHost() ); 118 119 buf.appendAscii( ",localPort=" ); 120 buf.append( (sal_Int32) nPort ); 121 buf.appendAscii( ",localHost=" ); 122 buf.append( m_socket.getLocalHost( ) ); 123 124 m_sDescription += buf.makeStringAndClear(); 125 } 126 read(Sequence<sal_Int8> & aReadBytes,sal_Int32 nBytesToRead)127 sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead ) 128 throw(::com::sun::star::io::IOException, 129 ::com::sun::star::uno::RuntimeException) 130 { 131 if( ! m_nStatus ) 132 { 133 notifyListeners(this, &_started, callStarted); 134 135 if( aReadBytes.getLength() != nBytesToRead ) 136 { 137 aReadBytes.realloc( nBytesToRead ); 138 } 139 sal_Int32 i = m_socket.read( aReadBytes.getArray() , aReadBytes.getLength() ); 140 141 if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None) 142 { 143 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - ")); 144 message += m_socket.getErrorAsString(); 145 146 IOException ioException(message, Reference<XInterface>(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 return i; 157 } 158 else 159 { 160 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - connection already closed")); 161 162 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 163 164 Any any; 165 any <<= ioException; 166 167 notifyListeners(this, &_error, callError(any)); 168 169 throw ioException; 170 } 171 } 172 write(const Sequence<sal_Int8> & seq)173 void SocketConnection::write( const Sequence < sal_Int8 > &seq ) 174 throw(::com::sun::star::io::IOException, 175 ::com::sun::star::uno::RuntimeException) 176 { 177 if( ! m_nStatus ) 178 { 179 if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() ) 180 { 181 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - ")); 182 message += m_socket.getErrorAsString(); 183 184 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 185 186 Any any; 187 any <<= ioException; 188 189 notifyListeners(this, &_error, callError(any)); 190 191 throw ioException; 192 } 193 } 194 else 195 { 196 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - connection already closed")); 197 198 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 199 200 Any any; 201 any <<= ioException; 202 203 notifyListeners(this, &_error, callError(any)); 204 205 throw ioException; 206 } 207 } 208 flush()209 void SocketConnection::flush( ) 210 throw(::com::sun::star::io::IOException, 211 ::com::sun::star::uno::RuntimeException) 212 { 213 214 } 215 close()216 void SocketConnection::close() 217 throw(::com::sun::star::io::IOException, 218 ::com::sun::star::uno::RuntimeException) 219 { 220 // ensure that close is called only once 221 if( 1 == osl_incrementInterlockedCount( (&m_nStatus) ) ) 222 { 223 m_socket.shutdown(); 224 notifyListeners(this, &_closed, callClosed); 225 } 226 } 227 getDescription()228 OUString SocketConnection::getDescription() 229 throw( ::com::sun::star::uno::RuntimeException) 230 { 231 return m_sDescription; 232 } 233 234 235 236 // XConnectionBroadcaster addStreamListener(const Reference<XStreamListener> & aListener)237 void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException) 238 { 239 MutexGuard guard(_mutex); 240 241 _listeners.insert(aListener); 242 } 243 removeStreamListener(const Reference<XStreamListener> & aListener)244 void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener) throw(RuntimeException) 245 { 246 MutexGuard guard(_mutex); 247 248 _listeners.erase(aListener); 249 } 250 } 251 252