27#include <com/sun/star/connection/XConnection.hpp>
28#include <com/sun/star/io/IOException.hpp>
29#include <com/sun/star/uno/Any.hxx>
30#include <com/sun/star/uno/Exception.hpp>
31#include <com/sun/star/uno/Reference.hxx>
32#include <com/sun/star/uno/RuntimeException.hpp>
33#include <com/sun/star/uno/Sequence.hxx>
34#include <com/sun/star/uno/Type.hxx>
35#include <com/sun/star/uno/XCurrentContext.hpp>
36#include <com/sun/star/uno/XInterface.hpp>
39#include <rtl/byteseq.h>
40#include <rtl/ustring.hxx>
43#include <typelib/typeclass.h>
44#include <typelib/typedescription.h>
45#include <typelib/typedescription.hxx>
60css::uno::Sequence< sal_Int8 > read(
61 css::uno::Reference< css::connection::XConnection >
const & connection,
62 sal_uInt32
size,
bool eofOk)
64 assert(connection.is());
65 if (
size > SAL_MAX_INT32) {
66 throw css::uno::RuntimeException(
67 "binaryurp::Reader: block size too large");
69 css::uno::Sequence< sal_Int8 > buf;
70 sal_Int32
n = connection->read(buf,
static_cast< sal_Int32
>(
size));
71 if (n == 0 && eofOk) {
72 return css::uno::Sequence< sal_Int8 >();
75 throw css::io::IOException(
76 "binaryurp::Reader: premature end of input");
82extern "C" void request(
void * pThreadSpecificData) {
83 assert(pThreadSpecificData !=
nullptr);
84 std::unique_ptr< IncomingRequest >(
85 static_cast< IncomingRequest *
>(pThreadSpecificData))->
92 Thread(
"binaryurpReader"), bridge_(bridge)
101 bridge_->sendRequestChangeRequest();
102 css::uno::Reference< css::connection::XConnection >
con(
105 css::uno::Sequence< sal_Int8 > s(read(
con, 8,
true));
106 if (!s.hasElements()) {
114 throw css::io::IOException(
115 "binaryurp::Reader: block with zero message count received");
118 for (sal_uInt32
i = 0;
i !=
count; ++
i) {
123 }
catch (
const css::uno::Exception & e) {
124 SAL_WARN(
"binaryurp",
"caught UNO exception '" << e <<
'\'');
125 }
catch (
const std::exception & e) {
126 SAL_WARN(
"binaryurp",
"caught C++ exception '" << e.what() <<
'\'');
137 bool forceSynchronous;
138 sal_uInt16 functionId;
139 if ((flags1 & 0x80) != 0) {
140 if ((flags1 & 0x40) == 0) {
144 newType = (flags1 & 0x20) != 0;
145 newOid = (flags1 & 0x10) != 0;
146 newTid = (flags1 & 0x08) != 0;
147 if ((flags1 & 0x01) != 0) {
149 forceSynchronous = (flags2 & 0x80) != 0;
150 if (((flags2 & 0x40) != 0) != forceSynchronous) {
152 throw css::uno::RuntimeException(
153 "URP: request message with MUSTREPLY != SYNCHRONOUS"
157 forceSynchronous =
false;
159 functionId = ((flags1 & 0x04) != 0)
165 forceSynchronous =
false;
166 functionId = ((flags1 & 0x40) != 0)
167 ? ((flags1 & 0x3F) << 8) | unmarshal.
read8() : flags1 & 0x3F;
169 css::uno::TypeDescription
type;
175 throw css::uno::RuntimeException(
176 "URP: request message with NEWTYPE received when last"
177 " interface type has not yet been set");
185 throw css::io::IOException(
186 "binaryurp::Unmarshal: empty OID");
191 throw css::uno::RuntimeException(
192 "URP: request message with NEWOID received when last OID has"
193 " not yet been set");
197 rtl::ByteSequence tid(
getTid(unmarshal, newTid));
200 if (
type.get()->eTypeClass != typelib_TypeClass_INTERFACE) {
201 throw css::uno::RuntimeException(
202 "URP: request message with non-interface interface type received");
204 typelib_InterfaceTypeDescription * itd =
205 reinterpret_cast< typelib_InterfaceTypeDescription *
>(
type.get());
206 if (functionId >= itd->nMapFunctionIndexToMemberIndex) {
207 throw css::uno::RuntimeException(
208 "URP: request message with unknown function ID received");
210 sal_Int32 memberId = itd->pMapFunctionIndexToMemberIndex[functionId];
211 css::uno::TypeDescription memberTd(itd->ppAllMembers[memberId]);
212 memberTd.makeComplete();
213 assert(memberTd.is());
214 bool protProps =
bridge_->isProtocolPropertiesRequest(oid,
type);
216 bridge_->isCurrentContextMode();
217 css::uno::UnoInterfaceReference cc;
219 css::uno::TypeDescription
t(
222 *
static_cast< uno_Interface **
>(
226 memberTd.get()->eTypeClass == typelib_TypeClass_INTERFACE_METHOD &&
227 (
reinterpret_cast< typelib_InterfaceMethodTypeDescription *
>(
231 !oneWay && forceSynchronous,
"binaryurp",
232 (
"superfluous MUSTREPLY/SYNCHRONOUS ignored in request message with"
233 " non-oneway function ID"));
234 bool synchronous = !oneWay || forceSynchronous;
235 bool bSetter =
false;
236 std::vector< BinaryAny > inArgs;
237 switch (memberTd.get()->eTypeClass) {
238 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
239 bSetter = itd->pMapMemberIndexToFunctionIndex[memberId] != functionId;
245 css::uno::TypeDescription(
247 typelib_InterfaceAttributeTypeDescription *
>(
249 pAttributeTypeRef)));
252 case typelib_TypeClass_INTERFACE_METHOD:
254 typelib_InterfaceMethodTypeDescription * mtd =
255 reinterpret_cast< typelib_InterfaceMethodTypeDescription *
>(
257 for (sal_Int32
i = 0;
i != mtd->nParams; ++
i) {
258 if (mtd->pParams[
i].bIn) {
261 css::uno::TypeDescription(
262 mtd->pParams[
i].pTypeRef)));
274 switch (functionId) {
276 bridge_->handleRequestChangeRequest(tid, inArgs);
279 bridge_->handleCommitChangeRequest(tid, inArgs);
282 throw css::uno::RuntimeException(
283 "URP: request message with UrpProtocolProperties OID and"
284 " unknown function ID received");
287 css::uno::UnoInterfaceReference obj;
288 switch (functionId) {
294 && inArgs[0].getType().equals(
295 css::uno::TypeDescription(
298 css::uno::TypeDescription(
301 css::uno::XInterface > >
::get()))
302 && (css::uno::TypeDescription(
304 typelib_TypeDescriptionReference **
>(
305 inArgs[0].getValue(inArgs[0].getType()))).
307 css::uno::TypeDescription(
310 css::uno::XInterface > >
::get())))))
312 throw css::uno::RuntimeException(
313 "URP: queryInterface request message with unknown OID '"
314 + oid +
"' received");
319 throw css::uno::RuntimeException(
320 "URP: request message with unknown function ID 1 received");
326 throw css::uno::RuntimeException(
327 "URP: request message with unknown OID received");
331 std::unique_ptr< IncomingRequest > req(
333 bridge_, tid, oid, obj,
type, functionId, synchronous, memberTd,
334 bSetter, std::move(inArgs), ccMode, cc));
336 bridge_->incrementActiveCalls();
339 bridge_->getThreadPool(), tid.getHandle(), req.get(), &request,
347 rtl::ByteSequence tid(
getTid(unmarshal, (flags1 & 0x08) != 0));
351 bool exc = (flags1 & 0x20) != 0;
353 std::vector< BinaryAny > outArgs;
358 (css::uno::TypeDescription(
364 typelib_TypeDescriptionReference **
p =
nullptr;
365 switch (req.
member.get()->eTypeClass) {
366 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
368 typelib_InterfaceAttributeTypeDescription * atd =
370 typelib_InterfaceAttributeTypeDescription *
>(
372 n = req.
setter ? atd->nSetExceptions : atd->nGetExceptions;
374 ? atd->ppSetExceptions : atd->ppGetExceptions;
377 case typelib_TypeClass_INTERFACE_METHOD:
379 typelib_InterfaceMethodTypeDescription * mtd =
381 typelib_InterfaceMethodTypeDescription *
>(
383 n = mtd->nExceptions;
384 p = mtd->ppExceptions;
392 for (sal_Int32
i = 0;
i !=
n; ++
i) {
395 reinterpret_cast< typelib_TypeDescriptionReference *
>(
403 throw css::uno::RuntimeException(
404 "URP: reply message with bad exception type received");
408 switch (req.
member.get()->eTypeClass) {
409 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
412 css::uno::TypeDescription(
414 typelib_InterfaceAttributeTypeDescription *
>(
419 case typelib_TypeClass_INTERFACE_METHOD:
421 typelib_InterfaceMethodTypeDescription * mtd =
423 typelib_InterfaceMethodTypeDescription *
>(
426 css::uno::TypeDescription(mtd->pReturnTypeRef));
427 for (sal_Int32
i = 0;
i != mtd->nParams; ++
i) {
428 if (mtd->pParams[
i].bOut) {
431 css::uno::TypeDescription(
432 mtd->pParams[
i].pTypeRef)));
445 std::unique_ptr< IncomingReply > resp(
448 bridge_->getThreadPool(), tid.getHandle(), resp.get(),
nullptr,
455 assert(outArgs.empty());
456 bridge_->handleRequestChangeReply(exc, ret);
459 assert(outArgs.empty());
460 bridge_->handleCommitChangeReply(exc, ret);
473 throw css::uno::RuntimeException(
474 "URP: message with NEWTID received when last TID has not yet been"
constexpr sal_Int8 header[]
com::sun::star::uno::TypeDescription getType() const noexcept
void * getValue(com::sun::star::uno::TypeDescription const &type) const noexcept
virtual void execute() override
com::sun::star::uno::TypeDescription lastType_
rtl::ByteSequence getTid(Unmarshal &unmarshal, bool newTid) const
virtual ~Reader() override
rtl::Reference< Bridge > bridge_
rtl::ByteSequence lastTid_
void readReplyMessage(Unmarshal &unmarshal, sal_uInt8 flags1)
Reader(rtl::Reference< Bridge > const &bridge)
void readMessage(Unmarshal &unmarshal)
rtl::ByteSequence readTid()
com::sun::star::uno::TypeDescription readType()
BinaryAny readValue(com::sun::star::uno::TypeDescription const &type)
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN(area, stream)
css::uno::UnoInterfaceReference get()
@ SPECIAL_FUNCTION_ID_COMMIT_CHANGE
@ SPECIAL_FUNCTION_ID_RELEASE
@ SPECIAL_FUNCTION_ID_REQUEST_CHANGE
@ SPECIAL_FUNCTION_ID_RESERVED
@ SPECIAL_FUNCTION_ID_QUERY_INTERFACE
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
com::sun::star::uno::TypeDescription member
void SAL_CALL uno_threadpool_putJob(uno_ThreadPool hPool, sal_Sequence *pThreadId, void *pJob, void(SAL_CALL *doRequest)(void *pThreadSpecificData), sal_Bool bIsOneway) SAL_THROW_EXTERN_C()
sal_Bool SAL_CALL typelib_typedescription_isAssignableFrom(typelib_TypeDescription *pAssignable, typelib_TypeDescription *pFrom) SAL_THROW_EXTERN_C()
sal_Bool SAL_CALL typelib_typedescriptionreference_isAssignableFrom(typelib_TypeDescriptionReference *pAssignable, typelib_TypeDescriptionReference *pFrom) SAL_THROW_EXTERN_C()