137adc4f0SAndrew Rist /**************************************************************
237adc4f0SAndrew Rist *
337adc4f0SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
437adc4f0SAndrew Rist * or more contributor license agreements. See the NOTICE file
537adc4f0SAndrew Rist * distributed with this work for additional information
637adc4f0SAndrew Rist * regarding copyright ownership. The ASF licenses this file
737adc4f0SAndrew Rist * to you under the Apache License, Version 2.0 (the
837adc4f0SAndrew Rist * "License"); you may not use this file except in compliance
937adc4f0SAndrew Rist * with the License. You may obtain a copy of the License at
1037adc4f0SAndrew Rist *
1137adc4f0SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
1237adc4f0SAndrew Rist *
1337adc4f0SAndrew Rist * Unless required by applicable law or agreed to in writing,
1437adc4f0SAndrew Rist * software distributed under the License is distributed on an
1537adc4f0SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1637adc4f0SAndrew Rist * KIND, either express or implied. See the License for the
1737adc4f0SAndrew Rist * specific language governing permissions and limitations
1837adc4f0SAndrew Rist * under the License.
1937adc4f0SAndrew Rist *
2037adc4f0SAndrew Rist *************************************************************/
2137adc4f0SAndrew Rist
2237adc4f0SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir #include "sal/config.h"
25cdf0e10cSrcweir
26cdf0e10cSrcweir #include <exception>
27cdf0e10cSrcweir #include <vector>
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include "com/sun/star/connection/XConnection.hpp"
30cdf0e10cSrcweir #include "com/sun/star/lang/WrappedTargetRuntimeException.hpp"
31cdf0e10cSrcweir #include "com/sun/star/uno/XCurrentContext.hpp"
32cdf0e10cSrcweir #include "cppuhelper/exc_hlp.hxx"
33cdf0e10cSrcweir #include "osl/mutex.hxx"
34cdf0e10cSrcweir #include "rtl/memory.h"
35cdf0e10cSrcweir #include "uno/dispatcher.hxx"
36cdf0e10cSrcweir
37cdf0e10cSrcweir #include "binaryany.hxx"
38cdf0e10cSrcweir #include "bridge.hxx"
39cdf0e10cSrcweir #include "currentcontext.hxx"
40cdf0e10cSrcweir #include "specialfunctionids.hxx"
41cdf0e10cSrcweir #include "writer.hxx"
42cdf0e10cSrcweir
43cdf0e10cSrcweir namespace binaryurp {
44cdf0e10cSrcweir
45cdf0e10cSrcweir namespace {
46cdf0e10cSrcweir
47cdf0e10cSrcweir namespace css = com::sun::star;
48cdf0e10cSrcweir
isProtocolPropertyMessage(rtl::OUString const & oid)49cdf0e10cSrcweir bool isProtocolPropertyMessage(rtl::OUString const & oid) {
50cdf0e10cSrcweir return oid.equalsAsciiL(
51cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("UrpProtocolProperties"));
52cdf0e10cSrcweir }
53cdf0e10cSrcweir
54cdf0e10cSrcweir }
55cdf0e10cSrcweir
Item()56cdf0e10cSrcweir Writer::Item::Item() {}
57cdf0e10cSrcweir
Item(rtl::ByteSequence const & theTid,rtl::OUString const & theOid,css::uno::TypeDescription const & theType,css::uno::TypeDescription const & theMember,std::vector<BinaryAny> const & inArguments,css::uno::UnoInterfaceReference const & theCurrentContext)58cdf0e10cSrcweir Writer::Item::Item(
59cdf0e10cSrcweir rtl::ByteSequence const & theTid, rtl::OUString const & theOid,
60cdf0e10cSrcweir css::uno::TypeDescription const & theType,
61cdf0e10cSrcweir css::uno::TypeDescription const & theMember,
62cdf0e10cSrcweir std::vector< BinaryAny > const & inArguments,
63cdf0e10cSrcweir css::uno::UnoInterfaceReference const & theCurrentContext):
64cdf0e10cSrcweir request(true), tid(theTid), oid(theOid), type(theType), member(theMember),
65cdf0e10cSrcweir arguments(inArguments), currentContext(theCurrentContext)
66cdf0e10cSrcweir {}
67cdf0e10cSrcweir
Item(rtl::ByteSequence const & theTid,css::uno::TypeDescription const & theMember,bool theSetter,bool theException,BinaryAny const & theReturnValue,std::vector<BinaryAny> const & outArguments,bool theSetCurrentContextMode)68cdf0e10cSrcweir Writer::Item::Item(
69cdf0e10cSrcweir rtl::ByteSequence const & theTid,
70cdf0e10cSrcweir css::uno::TypeDescription const & theMember, bool theSetter,
71cdf0e10cSrcweir bool theException, BinaryAny const & theReturnValue,
72cdf0e10cSrcweir std::vector< BinaryAny > const & outArguments,
73cdf0e10cSrcweir bool theSetCurrentContextMode):
74cdf0e10cSrcweir request(false), tid(theTid), member(theMember), setter(theSetter),
75cdf0e10cSrcweir arguments(outArguments), exception(theException),
76cdf0e10cSrcweir returnValue(theReturnValue), setCurrentContextMode(theSetCurrentContextMode)
77cdf0e10cSrcweir {}
78cdf0e10cSrcweir
Writer(rtl::Reference<Bridge> const & bridge)79cdf0e10cSrcweir Writer::Writer(rtl::Reference< Bridge > const & bridge):
80cdf0e10cSrcweir bridge_(bridge), marshal_(bridge, state_), stop_(false)
81cdf0e10cSrcweir {
82cdf0e10cSrcweir OSL_ASSERT(bridge.is());
83cdf0e10cSrcweir acquire();
84cdf0e10cSrcweir }
85cdf0e10cSrcweir
sendDirectRequest(rtl::ByteSequence const & tid,rtl::OUString const & oid,css::uno::TypeDescription const & type,css::uno::TypeDescription const & member,std::vector<BinaryAny> const & inArguments)86cdf0e10cSrcweir void Writer::sendDirectRequest(
87cdf0e10cSrcweir rtl::ByteSequence const & tid, rtl::OUString const & oid,
88cdf0e10cSrcweir css::uno::TypeDescription const & type,
89cdf0e10cSrcweir css::uno::TypeDescription const & member,
90cdf0e10cSrcweir std::vector< BinaryAny > const & inArguments)
91cdf0e10cSrcweir {
92cdf0e10cSrcweir OSL_ASSERT(!unblocked_.check());
93cdf0e10cSrcweir sendRequest(
94cdf0e10cSrcweir tid, oid, type, member, inArguments, false,
95cdf0e10cSrcweir css::uno::UnoInterfaceReference());
96cdf0e10cSrcweir }
97cdf0e10cSrcweir
sendDirectReply(rtl::ByteSequence const & tid,css::uno::TypeDescription const & member,bool exception,BinaryAny const & returnValue,std::vector<BinaryAny> const & outArguments)98cdf0e10cSrcweir void Writer::sendDirectReply(
99cdf0e10cSrcweir rtl::ByteSequence const & tid, css::uno::TypeDescription const & member,
100cdf0e10cSrcweir bool exception, BinaryAny const & returnValue,
101cdf0e10cSrcweir std::vector< BinaryAny > const & outArguments)
102cdf0e10cSrcweir {
103cdf0e10cSrcweir OSL_ASSERT(!unblocked_.check());
104cdf0e10cSrcweir sendReply(tid, member, false, exception, returnValue,outArguments);
105cdf0e10cSrcweir }
106cdf0e10cSrcweir
queueRequest(rtl::ByteSequence const & tid,rtl::OUString const & oid,css::uno::TypeDescription const & type,css::uno::TypeDescription const & member,std::vector<BinaryAny> const & inArguments)107cdf0e10cSrcweir void Writer::queueRequest(
108cdf0e10cSrcweir rtl::ByteSequence const & tid, rtl::OUString const & oid,
109cdf0e10cSrcweir css::uno::TypeDescription const & type,
110cdf0e10cSrcweir css::uno::TypeDescription const & member,
111cdf0e10cSrcweir std::vector< BinaryAny > const & inArguments)
112cdf0e10cSrcweir {
113cdf0e10cSrcweir css::uno::UnoInterfaceReference cc(current_context::get());
114cdf0e10cSrcweir osl::MutexGuard g(mutex_);
115cdf0e10cSrcweir queue_.push_back(Item(tid, oid, type, member, inArguments, cc));
116cdf0e10cSrcweir items_.set();
117cdf0e10cSrcweir }
118cdf0e10cSrcweir
queueReply(rtl::ByteSequence const & tid,com::sun::star::uno::TypeDescription const & member,bool setter,bool exception,BinaryAny const & returnValue,std::vector<BinaryAny> const & outArguments,bool setCurrentContextMode)119cdf0e10cSrcweir void Writer::queueReply(
120cdf0e10cSrcweir rtl::ByteSequence const & tid,
121cdf0e10cSrcweir com::sun::star::uno::TypeDescription const & member, bool setter,
122cdf0e10cSrcweir bool exception, BinaryAny const & returnValue,
123cdf0e10cSrcweir std::vector< BinaryAny > const & outArguments, bool setCurrentContextMode)
124cdf0e10cSrcweir {
125cdf0e10cSrcweir osl::MutexGuard g(mutex_);
126cdf0e10cSrcweir queue_.push_back(
127cdf0e10cSrcweir Item(
128cdf0e10cSrcweir tid, member, setter, exception, returnValue, outArguments,
129cdf0e10cSrcweir setCurrentContextMode));
130cdf0e10cSrcweir items_.set();
131cdf0e10cSrcweir }
132cdf0e10cSrcweir
unblock()133cdf0e10cSrcweir void Writer::unblock() {
134cdf0e10cSrcweir // Assumes that osl::Condition::set works as a memory barrier, so that
135cdf0e10cSrcweir // changes made by preceeding sendDirectRequest/Reply calls are visible to
136cdf0e10cSrcweir // subsequent sendRequest/Reply calls:
137cdf0e10cSrcweir unblocked_.set();
138cdf0e10cSrcweir }
139cdf0e10cSrcweir
stop()140cdf0e10cSrcweir void Writer::stop() {
141cdf0e10cSrcweir {
142cdf0e10cSrcweir osl::MutexGuard g(mutex_);
143cdf0e10cSrcweir stop_ = true;
144cdf0e10cSrcweir }
145cdf0e10cSrcweir unblocked_.set();
146cdf0e10cSrcweir items_.set();
147cdf0e10cSrcweir }
148cdf0e10cSrcweir
~Writer()149cdf0e10cSrcweir Writer::~Writer() {}
150cdf0e10cSrcweir
run()151cdf0e10cSrcweir void Writer::run() {
152cdf0e10cSrcweir setName("binaryurpWriter");
153cdf0e10cSrcweir try {
154cdf0e10cSrcweir unblocked_.wait();
155cdf0e10cSrcweir for (;;) {
156cdf0e10cSrcweir items_.wait();
157cdf0e10cSrcweir Item item;
158cdf0e10cSrcweir {
159cdf0e10cSrcweir osl::MutexGuard g(mutex_);
160cdf0e10cSrcweir if (stop_) {
161cdf0e10cSrcweir return;
162cdf0e10cSrcweir }
163cdf0e10cSrcweir OSL_ASSERT(!queue_.empty());
164cdf0e10cSrcweir item = queue_.front();
165cdf0e10cSrcweir queue_.pop_front();
166cdf0e10cSrcweir if (queue_.empty()) {
167cdf0e10cSrcweir items_.reset();
168cdf0e10cSrcweir }
169cdf0e10cSrcweir }
170cdf0e10cSrcweir if (item.request) {
171cdf0e10cSrcweir sendRequest(
172cdf0e10cSrcweir item.tid, item.oid, item.type, item.member, item.arguments,
173cdf0e10cSrcweir (!item.oid.equalsAsciiL(
174cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("UrpProtocolProperties")) &&
175cdf0e10cSrcweir !item.member.equals(
176cdf0e10cSrcweir css::uno::TypeDescription(
177cdf0e10cSrcweir rtl::OUString(
178cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM(
179cdf0e10cSrcweir "com.sun.star.uno.XInterface::"
180cdf0e10cSrcweir "release")))) &&
181cdf0e10cSrcweir bridge_->isCurrentContextMode()),
182cdf0e10cSrcweir item.currentContext);
183cdf0e10cSrcweir } else {
184cdf0e10cSrcweir sendReply(
185cdf0e10cSrcweir item.tid, item.member, item.setter, item.exception,
186cdf0e10cSrcweir item.returnValue, item.arguments);
187cdf0e10cSrcweir if (item.setCurrentContextMode) {
188cdf0e10cSrcweir bridge_->setCurrentContextMode();
189cdf0e10cSrcweir }
190cdf0e10cSrcweir }
191cdf0e10cSrcweir }
192cdf0e10cSrcweir } catch (css::uno::Exception & e) {
193cdf0e10cSrcweir OSL_TRACE(
194cdf0e10cSrcweir OSL_LOG_PREFIX "caught UNO exception '%s'",
195cdf0e10cSrcweir rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
196cdf0e10cSrcweir } catch (std::exception & e) {
197cdf0e10cSrcweir OSL_TRACE(OSL_LOG_PREFIX "caught C++ exception '%s'", e.what());
198cdf0e10cSrcweir }
199cdf0e10cSrcweir bridge_->terminate();
200cdf0e10cSrcweir }
201cdf0e10cSrcweir
onTerminated()202cdf0e10cSrcweir void Writer::onTerminated() {
203cdf0e10cSrcweir release();
204cdf0e10cSrcweir }
205cdf0e10cSrcweir
sendRequest(rtl::ByteSequence const & tid,rtl::OUString const & oid,css::uno::TypeDescription const & type,css::uno::TypeDescription const & member,std::vector<BinaryAny> const & inArguments,bool currentContextMode,css::uno::UnoInterfaceReference const & currentContext)206cdf0e10cSrcweir void Writer::sendRequest(
207cdf0e10cSrcweir rtl::ByteSequence const & tid, rtl::OUString const & oid,
208cdf0e10cSrcweir css::uno::TypeDescription const & type,
209cdf0e10cSrcweir css::uno::TypeDescription const & member,
210cdf0e10cSrcweir std::vector< BinaryAny > const & inArguments, bool currentContextMode,
211cdf0e10cSrcweir css::uno::UnoInterfaceReference const & currentContext)
212cdf0e10cSrcweir {
213*0848378bSHerbert Dürr OSL_ASSERT(tid.getLength() != 0 && !oid.isEmpty() && member.is());
214cdf0e10cSrcweir css::uno::TypeDescription t(type);
215cdf0e10cSrcweir sal_Int32 functionId = 0;
216cdf0e10cSrcweir bool forceSynchronous = false;
217cdf0e10cSrcweir member.makeComplete();
218cdf0e10cSrcweir switch (member.get()->eTypeClass) {
219cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_ATTRIBUTE:
220cdf0e10cSrcweir {
221cdf0e10cSrcweir typelib_InterfaceAttributeTypeDescription * atd =
222cdf0e10cSrcweir reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >(
223cdf0e10cSrcweir member.get());
224cdf0e10cSrcweir OSL_ASSERT(atd->pInterface != 0);
225cdf0e10cSrcweir if (!t.is()) {
226cdf0e10cSrcweir t = css::uno::TypeDescription(&atd->pInterface->aBase);
227cdf0e10cSrcweir }
228cdf0e10cSrcweir t.makeComplete();
229cdf0e10cSrcweir functionId = atd->pInterface->pMapMemberIndexToFunctionIndex[
230cdf0e10cSrcweir atd->aBase.nPosition];
231cdf0e10cSrcweir if (!inArguments.empty()) { // setter
232cdf0e10cSrcweir ++functionId;
233cdf0e10cSrcweir }
234cdf0e10cSrcweir break;
235cdf0e10cSrcweir }
236cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_METHOD:
237cdf0e10cSrcweir {
238cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * mtd =
239cdf0e10cSrcweir reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
240cdf0e10cSrcweir member.get());
241cdf0e10cSrcweir OSL_ASSERT(mtd->pInterface != 0);
242cdf0e10cSrcweir if (!t.is()) {
243cdf0e10cSrcweir t = css::uno::TypeDescription(&mtd->pInterface->aBase);
244cdf0e10cSrcweir }
245cdf0e10cSrcweir t.makeComplete();
246cdf0e10cSrcweir functionId = mtd->pInterface->pMapMemberIndexToFunctionIndex[
247cdf0e10cSrcweir mtd->aBase.nPosition];
248cdf0e10cSrcweir forceSynchronous = mtd->bOneWay &&
249cdf0e10cSrcweir functionId != SPECIAL_FUNCTION_ID_RELEASE;
250cdf0e10cSrcweir break;
251cdf0e10cSrcweir }
252cdf0e10cSrcweir default:
253cdf0e10cSrcweir OSL_ASSERT(false); // this cannot happen
254cdf0e10cSrcweir break;
255cdf0e10cSrcweir }
256cdf0e10cSrcweir OSL_ASSERT(functionId >= 0);
257cdf0e10cSrcweir if (functionId > SAL_MAX_UINT16) {
258cdf0e10cSrcweir throw css::uno::RuntimeException(
259cdf0e10cSrcweir rtl::OUString(
260cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("function ID too large for URP")),
261cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
262cdf0e10cSrcweir }
263cdf0e10cSrcweir std::vector< unsigned char > buf;
264cdf0e10cSrcweir bool newType = !(lastType_.is() && t.equals(lastType_));
265cdf0e10cSrcweir bool newOid = oid != lastOid_;
266cdf0e10cSrcweir bool newTid = tid != lastTid_;
267cdf0e10cSrcweir if (newType || newOid || newTid || forceSynchronous || functionId > 0x3FFF)
268cdf0e10cSrcweir // > 14 bit function ID
269cdf0e10cSrcweir {
270cdf0e10cSrcweir Marshal::write8(
271cdf0e10cSrcweir &buf,
272cdf0e10cSrcweir (0xC0 | (newType ? 0x20 : 0) | (newOid ? 0x10 : 0) |
273cdf0e10cSrcweir (newTid ? 0x08 : 0) | (functionId > 0xFF ? 0x04 : 0) |
274cdf0e10cSrcweir (forceSynchronous ? 0x01 : 0)));
275cdf0e10cSrcweir // bit 7: LONGHEADER, bit 6: REQUEST, bit 5: NEWTYPE, bit 4: NEWOID,
276cdf0e10cSrcweir // bit 3: NEWTID, bit 2: FUNCTIONID16, bit 0: MOREFLAGS
277cdf0e10cSrcweir if (forceSynchronous) {
278cdf0e10cSrcweir Marshal::write8(&buf, 0xC0); // bit 7: MUSTREPLY, bit 6: SYNCHRONOUS
279cdf0e10cSrcweir }
280cdf0e10cSrcweir if (functionId <= 0xFF) {
281cdf0e10cSrcweir Marshal::write8(&buf, static_cast< sal_uInt8 >(functionId));
282cdf0e10cSrcweir } else {
283cdf0e10cSrcweir Marshal::write16(&buf, static_cast< sal_uInt16 >(functionId));
284cdf0e10cSrcweir }
285cdf0e10cSrcweir if (newType) {
286cdf0e10cSrcweir marshal_.writeType(&buf, t);
287cdf0e10cSrcweir }
288cdf0e10cSrcweir if (newOid) {
289cdf0e10cSrcweir marshal_.writeOid(&buf, oid);
290cdf0e10cSrcweir }
291cdf0e10cSrcweir if (newTid) {
292cdf0e10cSrcweir marshal_.writeTid(&buf, tid);
293cdf0e10cSrcweir }
294cdf0e10cSrcweir } else if (functionId <= 0x3F) { // <= 6 bit function ID
295cdf0e10cSrcweir Marshal::write8(&buf, static_cast< sal_uInt8 >(functionId));
296cdf0e10cSrcweir // bit 7: !LONGHEADER, bit 6: !FUNCTIONID14
297cdf0e10cSrcweir } else {
298cdf0e10cSrcweir Marshal::write8(
299cdf0e10cSrcweir &buf, static_cast< sal_uInt8 >(0x40 | (functionId >> 8)));
300cdf0e10cSrcweir // bit 7: !LONGHEADER, bit 6: FUNCTIONID14
301cdf0e10cSrcweir Marshal::write8(&buf, functionId & 0xFF);
302cdf0e10cSrcweir }
303cdf0e10cSrcweir if (currentContextMode) {
304cdf0e10cSrcweir css::uno::UnoInterfaceReference cc(currentContext);
305cdf0e10cSrcweir marshal_.writeValue(
306cdf0e10cSrcweir &buf,
307cdf0e10cSrcweir css::uno::TypeDescription(
308cdf0e10cSrcweir cppu::UnoType<
309cdf0e10cSrcweir css::uno::Reference< css::uno::XCurrentContext > >::get()),
310cdf0e10cSrcweir BinaryAny(
311cdf0e10cSrcweir css::uno::TypeDescription(
312cdf0e10cSrcweir cppu::UnoType<
313cdf0e10cSrcweir css::uno::Reference<
314cdf0e10cSrcweir css::uno::XCurrentContext > >::get()),
315cdf0e10cSrcweir &cc.m_pUnoI));
316cdf0e10cSrcweir }
317cdf0e10cSrcweir switch (member.get()->eTypeClass) {
318cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_ATTRIBUTE:
319cdf0e10cSrcweir if (!inArguments.empty()) { // setter
320cdf0e10cSrcweir OSL_ASSERT(inArguments.size() == 1);
321cdf0e10cSrcweir marshal_.writeValue(
322cdf0e10cSrcweir &buf,
323cdf0e10cSrcweir css::uno::TypeDescription(
324cdf0e10cSrcweir reinterpret_cast<
325cdf0e10cSrcweir typelib_InterfaceAttributeTypeDescription * >(
326cdf0e10cSrcweir member.get())->
327cdf0e10cSrcweir pAttributeTypeRef),
328cdf0e10cSrcweir inArguments.front());
329cdf0e10cSrcweir }
330cdf0e10cSrcweir break;
331cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_METHOD:
332cdf0e10cSrcweir {
333cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * mtd =
334cdf0e10cSrcweir reinterpret_cast< typelib_InterfaceMethodTypeDescription * >(
335cdf0e10cSrcweir member.get());
336cdf0e10cSrcweir std::vector< BinaryAny >::const_iterator i(inArguments.begin());
337cdf0e10cSrcweir for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
338cdf0e10cSrcweir if (mtd->pParams[j].bIn) {
339cdf0e10cSrcweir marshal_.writeValue(
340cdf0e10cSrcweir &buf,
341cdf0e10cSrcweir css::uno::TypeDescription(mtd->pParams[j].pTypeRef),
342cdf0e10cSrcweir *i++);
343cdf0e10cSrcweir }
344cdf0e10cSrcweir }
345cdf0e10cSrcweir OSL_ASSERT(i == inArguments.end());
346cdf0e10cSrcweir break;
347cdf0e10cSrcweir }
348cdf0e10cSrcweir default:
349cdf0e10cSrcweir OSL_ASSERT(false); // this cannot happen
350cdf0e10cSrcweir break;
351cdf0e10cSrcweir }
352cdf0e10cSrcweir sendMessage(buf);
353cdf0e10cSrcweir lastType_ = t;
354cdf0e10cSrcweir lastOid_ = oid;
355cdf0e10cSrcweir lastTid_ = tid;
356cdf0e10cSrcweir }
357cdf0e10cSrcweir
sendReply(rtl::ByteSequence const & tid,com::sun::star::uno::TypeDescription const & member,bool setter,bool exception,BinaryAny const & returnValue,std::vector<BinaryAny> const & outArguments)358cdf0e10cSrcweir void Writer::sendReply(
359cdf0e10cSrcweir rtl::ByteSequence const & tid,
360cdf0e10cSrcweir com::sun::star::uno::TypeDescription const & member, bool setter,
361cdf0e10cSrcweir bool exception, BinaryAny const & returnValue,
362cdf0e10cSrcweir std::vector< BinaryAny > const & outArguments)
363cdf0e10cSrcweir {
364cdf0e10cSrcweir OSL_ASSERT(tid.getLength() != 0 && member.is() && member.get()->bComplete);
365cdf0e10cSrcweir std::vector< unsigned char > buf;
366cdf0e10cSrcweir bool newTid = tid != lastTid_;
367cdf0e10cSrcweir Marshal::write8(&buf, 0x80 | (exception ? 0x20 : 0) | (newTid ? 0x08 : 0));
368cdf0e10cSrcweir // bit 7: LONGHEADER; bit 6: !REQUEST; bit 5: EXCEPTION; bit 3: NEWTID
369cdf0e10cSrcweir if (newTid) {
370cdf0e10cSrcweir marshal_.writeTid(&buf, tid);
371cdf0e10cSrcweir }
372cdf0e10cSrcweir if (exception) {
373cdf0e10cSrcweir marshal_.writeValue(
374cdf0e10cSrcweir &buf,
375cdf0e10cSrcweir css::uno::TypeDescription(cppu::UnoType< css::uno::Any >::get()),
376cdf0e10cSrcweir returnValue);
377cdf0e10cSrcweir } else {
378cdf0e10cSrcweir switch (member.get()->eTypeClass) {
379cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_ATTRIBUTE:
380cdf0e10cSrcweir if (!setter) {
381cdf0e10cSrcweir marshal_.writeValue(
382cdf0e10cSrcweir &buf,
383cdf0e10cSrcweir css::uno::TypeDescription(
384cdf0e10cSrcweir reinterpret_cast<
385cdf0e10cSrcweir typelib_InterfaceAttributeTypeDescription * >(
386cdf0e10cSrcweir member.get())->
387cdf0e10cSrcweir pAttributeTypeRef),
388cdf0e10cSrcweir returnValue);
389cdf0e10cSrcweir }
390cdf0e10cSrcweir break;
391cdf0e10cSrcweir case typelib_TypeClass_INTERFACE_METHOD:
392cdf0e10cSrcweir {
393cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * mtd =
394cdf0e10cSrcweir reinterpret_cast<
395cdf0e10cSrcweir typelib_InterfaceMethodTypeDescription * >(
396cdf0e10cSrcweir member.get());
397cdf0e10cSrcweir marshal_.writeValue(
398cdf0e10cSrcweir &buf, css::uno::TypeDescription(mtd->pReturnTypeRef),
399cdf0e10cSrcweir returnValue);
400cdf0e10cSrcweir std::vector< BinaryAny >::const_iterator i(
401cdf0e10cSrcweir outArguments.begin());
402cdf0e10cSrcweir for (sal_Int32 j = 0; j != mtd->nParams; ++j) {
403cdf0e10cSrcweir if (mtd->pParams[j].bOut) {
404cdf0e10cSrcweir marshal_.writeValue(
405cdf0e10cSrcweir &buf,
406cdf0e10cSrcweir css::uno::TypeDescription(mtd->pParams[j].pTypeRef),
407cdf0e10cSrcweir *i++);
408cdf0e10cSrcweir }
409cdf0e10cSrcweir }
410cdf0e10cSrcweir OSL_ASSERT(i == outArguments.end());
411cdf0e10cSrcweir break;
412cdf0e10cSrcweir }
413cdf0e10cSrcweir default:
414cdf0e10cSrcweir OSL_ASSERT(false); // this cannot happen
415cdf0e10cSrcweir break;
416cdf0e10cSrcweir }
417cdf0e10cSrcweir }
418cdf0e10cSrcweir sendMessage(buf);
419cdf0e10cSrcweir lastTid_ = tid;
420cdf0e10cSrcweir bridge_->decrementCalls();
421cdf0e10cSrcweir }
422cdf0e10cSrcweir
sendMessage(std::vector<unsigned char> const & buffer)423cdf0e10cSrcweir void Writer::sendMessage(std::vector< unsigned char > const & buffer) {
424cdf0e10cSrcweir std::vector< unsigned char > header;
425cdf0e10cSrcweir if (buffer.size() > SAL_MAX_UINT32) {
426cdf0e10cSrcweir throw css::uno::RuntimeException(
427cdf0e10cSrcweir rtl::OUString(
428cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM("message too large for URP")),
429cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >());
430cdf0e10cSrcweir }
431cdf0e10cSrcweir Marshal::write32(&header, static_cast< sal_uInt32 >(buffer.size()));
432cdf0e10cSrcweir Marshal::write32(&header, 1);
433cdf0e10cSrcweir OSL_ASSERT(!buffer.empty());
434cdf0e10cSrcweir unsigned char const * p = &buffer[0];
435cdf0e10cSrcweir std::vector< unsigned char >::size_type n = buffer.size();
436cdf0e10cSrcweir OSL_ASSERT(header.size() <= SAL_MAX_INT32 && SAL_MAX_INT32 <= SAL_MAX_SIZE);
437cdf0e10cSrcweir sal_Size k = SAL_MAX_INT32 - header.size();
438cdf0e10cSrcweir if (n < k) {
439cdf0e10cSrcweir k = static_cast< sal_Size >(n);
440cdf0e10cSrcweir }
441cdf0e10cSrcweir css::uno::Sequence< sal_Int8 > s(
442cdf0e10cSrcweir static_cast< sal_Int32 >(header.size() + k));
443cdf0e10cSrcweir OSL_ASSERT(!header.empty());
444cdf0e10cSrcweir rtl_copyMemory(
445cdf0e10cSrcweir s.getArray(), &header[0], static_cast< sal_Size >(header.size()));
446cdf0e10cSrcweir for (;;) {
447cdf0e10cSrcweir rtl_copyMemory(s.getArray() + s.getLength() - k, p, k);
448cdf0e10cSrcweir try {
449cdf0e10cSrcweir bridge_->getConnection()->write(s);
450cdf0e10cSrcweir } catch (css::io::IOException & e) {
451cdf0e10cSrcweir css::uno::Any exc(cppu::getCaughtException());
452cdf0e10cSrcweir throw css::lang::WrappedTargetRuntimeException(
453cdf0e10cSrcweir (rtl::OUString(
454cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM(
455cdf0e10cSrcweir "Binary URP write raised IO exception: ")) +
456cdf0e10cSrcweir e.Message),
457cdf0e10cSrcweir css::uno::Reference< css::uno::XInterface >(), exc);
458cdf0e10cSrcweir }
459cdf0e10cSrcweir n = static_cast< std::vector< unsigned char >::size_type >(n - k);
460cdf0e10cSrcweir if (n == 0) {
461cdf0e10cSrcweir break;
462cdf0e10cSrcweir }
463cdf0e10cSrcweir p += k;
464cdf0e10cSrcweir k = SAL_MAX_INT32;
465cdf0e10cSrcweir if (n < k) {
466cdf0e10cSrcweir k = static_cast< sal_Size >(n);
467cdf0e10cSrcweir }
468cdf0e10cSrcweir s.realloc(k);
469cdf0e10cSrcweir }
470cdf0e10cSrcweir }
471cdf0e10cSrcweir
472cdf0e10cSrcweir }
473