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