1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: acc_socket.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_io.hxx"
33 #include "acceptor.hxx"
38 #include <rtl/ustrbuf.hxx>
39 #include <com/sun/star/connection/XConnectionBroadcaster.hpp>
40 #include <com/sun/star/connection/ConnectionSetupException.hpp>
42 #include <cppuhelper/implbase2.hxx>
44 using namespace ::osl
;
45 using namespace ::rtl
;
46 using namespace ::cppu
;
47 using namespace ::com::sun::star::uno
;
48 using namespace ::com::sun::star::io
;
49 using namespace ::com::sun::star::connection
;
52 namespace io_acceptor
{
56 size_t operator () (const ::com::sun::star::uno::Reference
<T
> & ref
) const
58 return (size_t)ref
.get();
65 sal_Bool
operator () (const ::com::sun::star::uno::Reference
<T
> & op1
,
66 const ::com::sun::star::uno::Reference
<T
> & op2
) const
68 return op1
.get() == op2
.get();
73 typedef ::std::hash_set
< ::com::sun::star::uno::Reference
< ::com::sun::star::io::XStreamListener
>,
74 ReferenceHash
< ::com::sun::star::io::XStreamListener
>,
75 ReferenceEqual
< ::com::sun::star::io::XStreamListener
> >
76 XStreamListener_hash_set
;
79 class SocketConnection
: public ::cppu::WeakImplHelper2
<
80 ::com::sun::star::connection::XConnection
,
81 ::com::sun::star::connection::XConnectionBroadcaster
>
85 SocketConnection( const OUString
& sConnectionDescription
);
88 virtual sal_Int32 SAL_CALL
read( ::com::sun::star::uno::Sequence
< sal_Int8
>& aReadBytes
,
89 sal_Int32 nBytesToRead
)
90 throw(::com::sun::star::io::IOException
,
91 ::com::sun::star::uno::RuntimeException
);
92 virtual void SAL_CALL
write( const ::com::sun::star::uno::Sequence
< sal_Int8
>& aData
)
93 throw(::com::sun::star::io::IOException
,
94 ::com::sun::star::uno::RuntimeException
);
95 virtual void SAL_CALL
flush( ) throw(
96 ::com::sun::star::io::IOException
,
97 ::com::sun::star::uno::RuntimeException
);
98 virtual void SAL_CALL
close( )
99 throw(::com::sun::star::io::IOException
,
100 ::com::sun::star::uno::RuntimeException
);
101 virtual ::rtl::OUString SAL_CALL
getDescription( )
102 throw(::com::sun::star::uno::RuntimeException
);
104 // XConnectionBroadcaster
105 virtual void SAL_CALL
addStreamListener(const ::com::sun::star::uno::Reference
< ::com::sun::star::io::XStreamListener
>& aListener
)
106 throw(::com::sun::star::uno::RuntimeException
);
107 virtual void SAL_CALL
removeStreamListener(const ::com::sun::star::uno::Reference
< ::com::sun::star::io::XStreamListener
>& aListener
)
108 throw(::com::sun::star::uno::RuntimeException
);
111 void completeConnectionString();
113 ::osl::StreamSocket m_socket
;
114 ::osl::SocketAddr m_addr
;
115 oslInterlockedCount m_nStatus
;
116 ::rtl::OUString m_sDescription
;
122 XStreamListener_hash_set _listeners
;
126 void notifyListeners(SocketConnection
* pCon
, sal_Bool
* notified
, T t
)
128 XStreamListener_hash_set listeners
;
131 ::osl::MutexGuard
guard(pCon
->_mutex
);
134 *notified
= sal_True
;
135 listeners
= pCon
->_listeners
;
139 ::std::for_each(listeners
.begin(), listeners
.end(), t
);
142 static void callStarted(Reference
<XStreamListener
> xStreamListener
)
144 xStreamListener
->started();
150 callError(const Any
& any
);
152 void operator () (Reference
<XStreamListener
> xStreamListener
);
155 callError::callError(const Any
& aAny
)
160 void callError::operator () (Reference
<XStreamListener
> xStreamListener
)
162 xStreamListener
->error(any
);
165 static void callClosed(Reference
<XStreamListener
> xStreamListener
)
167 xStreamListener
->closed();
171 SocketConnection::SocketConnection( const OUString
&sConnectionDescription
) :
173 m_sDescription( sConnectionDescription
),
178 g_moduleCount
.modCnt
.acquire( &g_moduleCount
.modCnt
);
180 m_sDescription
+= OUString( RTL_CONSTASCII_USTRINGPARAM( ",uniqueValue=" ) );
181 m_sDescription
+= OUString::valueOf(
182 sal::static_int_cast
< sal_Int64
>(
183 reinterpret_cast< sal_IntPtr
>(&m_socket
)),
187 SocketConnection::~SocketConnection()
189 g_moduleCount
.modCnt
.release( &g_moduleCount
.modCnt
);
192 void SocketConnection::completeConnectionString()
194 OUStringBuffer
buf( 256 );
195 buf
.appendAscii( ",peerPort=" );
196 buf
.append( (sal_Int32
) m_socket
.getPeerPort() );
197 buf
.appendAscii( ",peerHost=" );
198 buf
.append( m_socket
.getPeerHost( ) );
200 buf
.appendAscii( ",localPort=" );
201 buf
.append( (sal_Int32
) m_socket
.getLocalPort() );
202 buf
.appendAscii( ",localHost=" );
203 buf
.append( m_socket
.getLocalHost() );
205 m_sDescription
+= buf
.makeStringAndClear();
208 sal_Int32
SocketConnection::read( Sequence
< sal_Int8
> & aReadBytes
, sal_Int32 nBytesToRead
)
209 throw(::com::sun::star::io::IOException
,
210 ::com::sun::star::uno::RuntimeException
)
214 notifyListeners(this, &_started
, callStarted
);
216 if( aReadBytes
.getLength() != nBytesToRead
)
218 aReadBytes
.realloc( nBytesToRead
);
222 i
= m_socket
.read( aReadBytes
.getArray() , aReadBytes
.getLength() );
224 if(i
!= nBytesToRead
)
226 OUString
message(RTL_CONSTASCII_USTRINGPARAM("acc_socket.cxx:SocketConnection::read: error - "));
227 message
+= m_socket
.getErrorAsString();
229 IOException
ioException(message
, Reference
<XInterface
>(static_cast<XConnection
*>(this)));
234 notifyListeners(this, &_error
, callError(any
));
243 OUString
message(RTL_CONSTASCII_USTRINGPARAM("acc_socket.cxx:SocketConnection::read: error - connection already closed"));
245 IOException
ioException(message
, Reference
<XInterface
>(static_cast<XConnection
*>(this)));
250 notifyListeners(this, &_error
, callError(any
));
256 void SocketConnection::write( const Sequence
< sal_Int8
> &seq
)
257 throw(::com::sun::star::io::IOException
,
258 ::com::sun::star::uno::RuntimeException
)
262 if( m_socket
.write( seq
.getConstArray() , seq
.getLength() ) != seq
.getLength() )
264 OUString
message(RTL_CONSTASCII_USTRINGPARAM("acc_socket.cxx:SocketConnection::write: error - "));
265 message
+= m_socket
.getErrorAsString();
267 IOException
ioException(message
, Reference
<XInterface
>(static_cast<XConnection
*>(this)));
272 notifyListeners(this, &_error
, callError(any
));
279 OUString
message(RTL_CONSTASCII_USTRINGPARAM("acc_socket.cxx:SocketConnection::write: error - connection already closed"));
281 IOException
ioException(message
, Reference
<XInterface
>(static_cast<XConnection
*>(this)));
286 notifyListeners(this, &_error
, callError(any
));
292 void SocketConnection::flush( )
293 throw(::com::sun::star::io::IOException
,
294 ::com::sun::star::uno::RuntimeException
)
299 void SocketConnection::close()
300 throw(::com::sun::star::io::IOException
,
301 ::com::sun::star::uno::RuntimeException
)
303 // enshure close is called only once
304 if( 1 == osl_incrementInterlockedCount( (&m_nStatus
) ) )
307 notifyListeners(this, &_closed
, callClosed
);
311 OUString
SocketConnection::getDescription()
312 throw( ::com::sun::star::uno::RuntimeException
)
314 return m_sDescription
;
318 // XConnectionBroadcaster
319 void SAL_CALL
SocketConnection::addStreamListener(const Reference
<XStreamListener
> & aListener
) throw(RuntimeException
)
321 MutexGuard
guard(_mutex
);
323 _listeners
.insert(aListener
);
326 void SAL_CALL
SocketConnection::removeStreamListener(const Reference
<XStreamListener
> & aListener
) throw(RuntimeException
)
328 MutexGuard
guard(_mutex
);
330 _listeners
.erase(aListener
);
333 SocketAcceptor::SocketAcceptor( const OUString
&sSocketName
,
335 sal_Bool bTcpNoDelay
,
336 const OUString
&sConnectionDescription
) :
337 m_sSocketName( sSocketName
),
338 m_sConnectionDescription( sConnectionDescription
),
340 m_bTcpNoDelay( bTcpNoDelay
),
341 m_bClosed( sal_False
)
346 void SocketAcceptor::init()
348 if( ! m_addr
.setPort( m_nPort
) )
350 OUStringBuffer
message( 128 );
351 message
.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - invalid tcp/ip port " );
352 message
.append( (sal_Int32
) m_nPort
);
353 throw ConnectionSetupException(
354 message
.makeStringAndClear() , Reference
< XInterface
> () );
356 if( ! m_addr
.setHostname( m_sSocketName
.pData
) )
358 OUStringBuffer
message( 128 );
359 message
.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - invalid host " );
360 message
.append( m_sSocketName
);
361 throw ConnectionSetupException(
362 message
.makeStringAndClear(), Reference
< XInterface
> () );
364 m_socket
.setOption( osl_Socket_OptionReuseAddr
, 1);
366 if(! m_socket
.bind(m_addr
) )
368 OUStringBuffer
message( 128 );
369 message
.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - couldn't bind on " );
370 message
.append( m_sSocketName
).appendAscii( ":" ).append((sal_Int32
)m_nPort
);
371 throw ConnectionSetupException(
372 message
.makeStringAndClear(),
373 Reference
<XInterface
>());
376 if(! m_socket
.listen() )
378 OUStringBuffer
message( 128 );
379 message
.appendAscii( "acc_socket.cxx:SocketAcceptor::init - error - can't listen on " );
380 message
.append( m_sSocketName
).appendAscii( ":" ).append( (sal_Int32
) m_nPort
);
381 throw ConnectionSetupException( message
.makeStringAndClear(),Reference
<XInterface
>() );
385 Reference
< XConnection
> SocketAcceptor::accept( )
387 SocketConnection
*pConn
= new SocketConnection( m_sConnectionDescription
);
389 if( m_socket
.acceptConnection( pConn
->m_socket
)!= osl_Socket_Ok
)
391 // stopAccepting was called
393 return Reference
< XConnection
> ();
398 return Reference
< XConnection
> ();
401 pConn
->completeConnectionString();
404 sal_Int32 nTcpNoDelay
= sal_True
;
405 pConn
->m_socket
.setOption( osl_Socket_OptionTcpNoDelay
, &nTcpNoDelay
,
406 sizeof( nTcpNoDelay
) , osl_Socket_LevelTcp
);
409 return Reference
< XConnection
> ( (XConnection
* ) pConn
);
412 void SocketAcceptor::stopAccepting()
414 m_bClosed
= sal_True
;