xref: /aoo41x/main/binaryurp/source/writer.cxx (revision 0848378b)
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