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> 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 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 70 callError::callError(const Any & aAny) 71 : any(aAny) 72 { 73 } 74 75 void callError::operator () (Reference<XStreamListener> xStreamListener) 76 { 77 xStreamListener->error(any); 78 } 79 80 static void callClosed(Reference<XStreamListener> xStreamListener) 81 { 82 xStreamListener->closed(); 83 } 84 85 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 102 SocketConnection::~SocketConnection() 103 { 104 g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); 105 } 106 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 127 sal_Int32 SocketConnection::read( Sequence < sal_Int8 > & aReadBytes , sal_Int32 nBytesToRead ) 128 { 129 if( ! m_nStatus ) 130 { 131 notifyListeners(this, &_started, callStarted); 132 133 if( aReadBytes.getLength() != nBytesToRead ) 134 { 135 aReadBytes.realloc( nBytesToRead ); 136 } 137 sal_Int32 i = m_socket.read( aReadBytes.getArray() , aReadBytes.getLength() ); 138 139 if(i != nBytesToRead && m_socket.getError() != osl_Socket_E_None) 140 { 141 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - ")); 142 message += m_socket.getErrorAsString(); 143 144 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 145 146 Any any; 147 any <<= ioException; 148 149 notifyListeners(this, &_error, callError(any)); 150 151 throw ioException; 152 } 153 154 return i; 155 } 156 else 157 { 158 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::read: error - connection already closed")); 159 160 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 161 162 Any any; 163 any <<= ioException; 164 165 notifyListeners(this, &_error, callError(any)); 166 167 throw ioException; 168 } 169 } 170 171 void SocketConnection::write( const Sequence < sal_Int8 > &seq ) 172 { 173 if( ! m_nStatus ) 174 { 175 if( m_socket.write( seq.getConstArray() , seq.getLength() ) != seq.getLength() ) 176 { 177 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - ")); 178 message += m_socket.getErrorAsString(); 179 180 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 181 182 Any any; 183 any <<= ioException; 184 185 notifyListeners(this, &_error, callError(any)); 186 187 throw ioException; 188 } 189 } 190 else 191 { 192 OUString message(RTL_CONSTASCII_USTRINGPARAM("ctr_socket.cxx:SocketConnection::write: error - connection already closed")); 193 194 IOException ioException(message, Reference<XInterface>(static_cast<XConnection *>(this))); 195 196 Any any; 197 any <<= ioException; 198 199 notifyListeners(this, &_error, callError(any)); 200 201 throw ioException; 202 } 203 } 204 205 void SocketConnection::flush( ) 206 { 207 208 } 209 210 void SocketConnection::close() 211 { 212 // ensure that close is called only once 213 if( 1 == osl_incrementInterlockedCount( (&m_nStatus) ) ) 214 { 215 m_socket.shutdown(); 216 notifyListeners(this, &_closed, callClosed); 217 } 218 } 219 220 OUString SocketConnection::getDescription() 221 { 222 return m_sDescription; 223 } 224 225 226 227 // XConnectionBroadcaster 228 void SAL_CALL SocketConnection::addStreamListener(const Reference<XStreamListener> & aListener) 229 { 230 MutexGuard guard(_mutex); 231 232 _listeners.insert(aListener); 233 } 234 235 void SAL_CALL SocketConnection::removeStreamListener(const Reference<XStreamListener> & aListener) 236 { 237 MutexGuard guard(_mutex); 238 239 _listeners.erase(aListener); 240 } 241 } 242