1 // -*- Mode: C++; -*-
2 // Package : omniORB
3 // GIOP_S.cc Created on: 05/01/2001
4 // Author : Sai Lai Lo (sll)
5 //
6 // Copyright (C) 2002-2011 Apasphere Ltd
7 // Copyright (C) 2001 AT&T Laboratories Cambridge
8 //
9 // This file is part of the omniORB library
10 //
11 // The omniORB library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library. If not, see http://www.gnu.org/licenses/
23 //
24 //
25 // Description:
26 // *** PROPRIETARY INTERFACE ***
27 //
28
29 #include <omniORB4/CORBA.h>
30 #include <omniORB4/callDescriptor.h>
31 #include <omniORB4/callHandle.h>
32 #include <initRefs.h>
33 #include <exceptiondefs.h>
34 #include <objectTable.h>
35 #include <objectAdapter.h>
36 #include <giopStrand.h>
37 #include <giopStream.h>
38 #include <giopStreamImpl.h>
39 #include <invoker.h>
40 #include <giopServer.h>
41 #include <giopWorker.h>
42 #include <GIOP_S.h>
43 #include <omniORB4/minorCode.h>
44 #include <omniORB4/omniInterceptors.h>
45 #include <interceptors.h>
46 #include <poaimpl.h>
47 #include <orbParameters.h>
48
49 #ifdef HAVE_STD
50 #include <memory>
51 #endif
52
OMNI_NAMESPACE_BEGIN(omni)53 OMNI_NAMESPACE_BEGIN(omni)
54
55 ////////////////////////////////////////////////////////////////////////
56 GIOP_S_Holder::GIOP_S_Holder(giopStrand* g, giopWorker* work) : pd_strand(g) {
57 pd_iop_s = g->acquireServer(work);
58 }
59
60
61 ////////////////////////////////////////////////////////////////////////
~GIOP_S_Holder()62 GIOP_S_Holder::~GIOP_S_Holder() {
63 if (pd_iop_s) pd_strand->releaseServer(pd_iop_s);
64 }
65
66 ////////////////////////////////////////////////////////////////////////
GIOP_S(giopStrand * g)67 GIOP_S::GIOP_S(giopStrand* g) : giopStream(g),
68 pd_state(UnUsed),
69 pd_worker(0),
70 pd_calldescriptor(0),
71 pd_requestType(GIOP::MessageError),
72 pd_operation((char*)pd_op_buffer),
73 pd_principal(pd_pr_buffer),
74 pd_principal_len(0),
75 pd_response_expected(1),
76 pd_result_expected(1)
77 {
78 }
79
80 ////////////////////////////////////////////////////////////////////////
GIOP_S(const GIOP_S & src)81 GIOP_S::GIOP_S(const GIOP_S& src) : giopStream(src.pd_strand),
82 pd_state(UnUsed),
83 pd_worker(0),
84 pd_calldescriptor(0),
85 pd_requestType(GIOP::MessageError),
86 pd_operation((char*)pd_op_buffer),
87 pd_principal(pd_pr_buffer),
88 pd_principal_len(0),
89 pd_response_expected(1),
90 pd_result_expected(1)
91 {
92 }
93
94 ////////////////////////////////////////////////////////////////////////
~GIOP_S()95 GIOP_S::~GIOP_S() {
96 if (pd_operation != (char*)pd_op_buffer) delete [] pd_operation;
97 if (pd_principal != pd_pr_buffer) delete [] pd_principal;
98 }
99
100 ////////////////////////////////////////////////////////////////////////
101 void*
ptrToClass(int * cptr)102 GIOP_S::ptrToClass(int* cptr)
103 {
104 if (cptr == &GIOP_S ::_classid) return (GIOP_S*) this;
105 if (cptr == &giopStream::_classid) return (giopStream*)this;
106 if (cptr == &cdrStream ::_classid) return (cdrStream*) this;
107
108 return 0;
109 }
110 int GIOP_S::_classid;
111
112
113 ////////////////////////////////////////////////////////////////////////
114 static inline void
setServerDeadline(GIOP_S * giop_s)115 setServerDeadline(GIOP_S* giop_s)
116 {
117 if (orbParameters::serverCallTimeOutPeriod) {
118
119 omni_time_t deadline;
120 omni_thread::get_time(deadline, orbParameters::serverCallTimeOutPeriod);
121 giop_s->setDeadline(deadline);
122 }
123 }
124
125 ////////////////////////////////////////////////////////////////////////
126 CORBA::Boolean
dispatcher()127 GIOP_S::dispatcher() {
128
129 OMNIORB_ASSERT(pd_state == Idle);
130
131 try {
132
133 pd_state = WaitForRequestHeader;
134 calldescriptor(0);
135 requestId(0xffffffff);
136
137 impl()->inputMessageBegin(this,impl()->unmarshalWildCardRequestHeader);
138
139 {
140 omni_tracedmutex_lock sync(*omniTransportLock);
141 pd_state = RequestHeaderIsBeingProcessed;
142 if (!pd_strand->stopIdleCounter()) {
143 // This strand has been expired by the scavenger. Don't
144 // process this call.
145 omniORB::logs(5, "Connection closed by scavenger. Dispatch aborted.");
146 pd_strand->state(giopStrand::DYING);
147 return 0;
148 }
149 }
150 setServerDeadline(this);
151
152 if (pd_requestType == GIOP::Request) {
153 return handleRequest();
154 }
155 else if (pd_requestType == GIOP::LocateRequest) {
156 return handleLocateRequest();
157 }
158 else if (pd_requestType == GIOP::CancelRequest) {
159 return handleCancelRequest();
160 }
161 else {
162 if( omniORB::trace(1) ) {
163 omniORB::logger l;
164 l << "Unexpected message type (" << (CORBA::ULong) pd_requestType
165 << ") received by a server thread at "
166 << __FILE__ << ": line " << __LINE__ << "\n";
167 }
168 return 0;
169 }
170 }
171 catch(const giopStream::CommFailure&) {
172 // Connection has been closed.
173 return 0;
174 }
175
176 #ifndef HAS_Cplusplus_catch_exception_by_base
177 # define CATCH_AND_HANDLE(name) \
178 catch(CORBA::name& ex) { \
179 impl()->sendMsgErrorMessage(this, &ex); \
180 return 0; \
181 }
182
183 OMNIORB_FOR_EACH_SYS_EXCEPTION(CATCH_AND_HANDLE)
184
185 # undef CATCH_AND_HANDLE
186 #endif
187
188 catch(CORBA::SystemException& ex) {
189 impl()->sendMsgErrorMessage(this, &ex);
190 return 0;
191 }
192
193 catch(const omniORB::fatalException& ex) {
194 if( omniORB::trace(1) ) {
195 omniORB::logger l;
196 l << "omniORB fatalException caught by a server thread at "
197 << ex.file() << ": line "
198 << ex.line() << ", message: "
199 << ex.errmsg() << "\n";
200 }
201 return 0;
202 }
203 catch (...) {
204 if ( omniORB::trace(1) ) {
205 omniORB::logger l;
206 l << "Unknown exception caught by a server thread at "
207 << __FILE__ << ": line " << __LINE__ << "\n";
208 }
209 return 0;
210 }
211 }
212
213 ////////////////////////////////////////////////////////////////////////
214 CORBA::Boolean
handleRequest()215 GIOP_S::handleRequest() {
216
217 try {
218
219 impl()->unmarshalRequestHeader(this);
220
221 pd_state = RequestIsBeingProcessed;
222
223 {
224 omniInterceptors::serverReceiveRequest_T::info_T info(*this);
225 omniInterceptorP::visit(info);
226 }
227
228 // Create a callHandle object
229 omniCallHandle call_handle(this, pd_worker->selfThread());
230
231 // Can we find the object in the local object table?
232 if (keysize() < 0)
233 OMNIORB_THROW(OBJECT_NOT_EXIST,OBJECT_NOT_EXIST_NoMatch,
234 CORBA::COMPLETED_NO);
235
236 CORBA::ULong hash = omni::hash(key(), keysize());
237
238 omni::internalLock->lock();
239 omniLocalIdentity* id;
240 id = omniObjTable::locateActive(key(), keysize(), hash, 1);
241
242 if( id ) {
243 id->dispatch(call_handle);
244 return 1;
245 }
246
247 omni::internalLock->unlock();
248
249 // Can we create a suitable object on demand?
250
251 omniObjAdapter_var adapter(omniObjAdapter::getAdapter(key(),keysize()));
252
253 if( adapter ) {
254 adapter->dispatch(call_handle, key(), keysize());
255 return 1;
256 }
257
258 // Or is it the bootstrap agent?
259
260 if( keysize() == 4 && !memcmp(key(), "INIT", 4) &&
261 omniInitialReferences::invoke_bootstrap_agentImpl(call_handle) )
262 return 1;
263
264 // Oh dear.
265
266 if (omniObjAdapter::isDeactivating())
267 OMNIORB_THROW(OBJ_ADAPTER,
268 OBJ_ADAPTER_POAUnknownAdapter,
269 CORBA::COMPLETED_NO);
270 else
271 OMNIORB_THROW(OBJECT_NOT_EXIST,
272 OBJECT_NOT_EXIST_NoMatch,
273 CORBA::COMPLETED_NO);
274 }
275 catch(omniORB::LOCATION_FORWARD& ex) {
276 // This is here to provide a convenient way to implement
277 // location forwarding. The object implementation can throw
278 // a location forward exception to re-direct the request
279 // to another location.
280
281 if( omniORB::traceInvocations ) {
282 omniORB::logger l;
283 l << "Implementation of '" << operation()
284 << "' generated LOCATION_FORWARD.\n";
285 }
286
287 CORBA::Object_var release_it(ex.get_obj());
288 if (pd_state == RequestIsBeingProcessed) {
289 SkipRequestBody();
290 }
291 if (response_expected()) {
292 setServerDeadline(this);
293 impl()->sendLocationForwardReply(this,release_it,ex.is_permanent());
294 }
295 // If the client does not expect a response, we quietly drop
296 // the location forward.
297 }
298 catch (const terminateProcessing&) {
299 }
300
301 #define MARSHAL_USER_EXCEPTION() do { \
302 if (pd_state == RequestIsBeingProcessed) { \
303 SkipRequestBody(); \
304 } \
305 if (response_expected()) { \
306 setServerDeadline(this); \
307 if (calldescriptor()) { \
308 int i, repoid_size; \
309 const char* repoid = ex._NP_repoId(&repoid_size); \
310 for( i = 0; i < pd_n_user_excns; i++ ) \
311 if( omni::strMatch(pd_user_excns[i], repoid) ) { \
312 impl()->sendUserException(this,ex); \
313 break; \
314 } \
315 if( i == pd_n_user_excns ) { \
316 if( omniORB::trace(1) ) { \
317 omniORB::logger l; \
318 l << "Warning: method '" << operation() \
319 << "' on: " << pd_key \
320 << " raised the exception: " << repoid << '\n'; \
321 } \
322 CORBA::UNKNOWN sex(UNKNOWN_UserException, \
323 (CORBA::CompletionStatus) completion()); \
324 impl()->sendSystemException(this,sex); \
325 } \
326 } \
327 else { \
328 impl()->sendUserException(this,ex); \
329 } \
330 } \
331 } while (0)
332
333 #define MARSHAL_SYSTEM_EXCEPTION() do { \
334 setServerDeadline(this); \
335 if (pd_state == RequestIsBeingProcessed) { \
336 SkipRequestBody(); \
337 } \
338 if (pd_state == WaitForRequestHeader || \
339 pd_state == RequestHeaderIsBeingProcessed ) { \
340 impl()->sendMsgErrorMessage(this, &ex); \
341 return 0; \
342 } else if (response_expected()) { \
343 impl()->sendSystemException(this,ex); \
344 } \
345 } while (0)
346
347 # ifndef HAS_Cplusplus_catch_exception_by_base
348
349 // We have to catch each type of system exception separately
350 // here to support compilers which cannot catch more derived
351 // types.
352 # define CATCH_AND_MARSHAL(name) \
353 catch (CORBA::name& ex) { \
354 MARSHAL_SYSTEM_EXCEPTION(); \
355 }
356
357 OMNIORB_FOR_EACH_SYS_EXCEPTION(CATCH_AND_MARSHAL)
358
359 # undef CATCH_AND_MARSHAL
360
361 catch(omniORB::StubUserException& uex) {
362 CORBA::UserException& ex = *((CORBA::UserException*)uex.ex());
363 MARSHAL_USER_EXCEPTION();
364 delete uex.ex(); // ?? Possible memory leak?
365 }
366
367 #endif
368
369
370 catch(CORBA::SystemException& ex) {
371 MARSHAL_SYSTEM_EXCEPTION();
372 // If the client does not expect a response, we quietly drop
373 // the system exception.
374 }
375 catch(CORBA::UserException& ex) {
376 MARSHAL_USER_EXCEPTION();
377 }
378 #undef MARSHAL_USER_EXCEPTION
379 #undef MARSHAL_SYSTEM_EXCEPTION
380
381 catch(const giopStream::CommFailure&) {
382 throw;
383 }
384
385 #ifdef HAVE_STD
386 catch (const std::bad_alloc&) {
387 // We keep logging as simple as possible to avoid too much allocation.
388 omniORB::logs(1, "Error: upcall raised std::bad_alloc.");
389
390 if (response_expected()) {
391 CORBA::NO_MEMORY ex(NO_MEMORY_BadAlloc,
392 (CORBA::CompletionStatus)completion());
393 impl()->sendSystemException(this,ex);
394 }
395 }
396
397 catch (const std::exception& std_ex) {
398 if (omniORB::trace(1)) {
399 omniORB::logger l;
400 l << "Warning: method '" << operation() << "' raised an unexpected "
401 << "std::exception (not a CORBA exception): "
402 << std_ex.what() << "\n";
403 }
404 if (response_expected()) {
405 CORBA::UNKNOWN ex(UNKNOWN_UserException,
406 (CORBA::CompletionStatus) completion());
407 impl()->sendSystemException(this,ex);
408 }
409 }
410 #endif // HAVE_STD
411
412 catch (const omni_thread_fatal& thr_ex) {
413 if (omniORB::trace(1)) {
414 omniORB::logger l;
415 l << "Warning: method '" << operation() << "' raised an "
416 << "omni_thread_fatal exception (error " << thr_ex.error << ").\n";
417 }
418 if (response_expected()) {
419 CORBA::UNKNOWN ex(UNKNOWN_OmniThreadException,
420 (CORBA::CompletionStatus) completion());
421 impl()->sendSystemException(this,ex);
422 }
423 }
424
425 catch(...) {
426 if (omniORB::trace(1)) {
427 omniORB::logger l;
428 l << "Warning: method '" << operation() << "' raised an unexpected "
429 "exception (not a CORBA exception).\n";
430 }
431 if (response_expected()) {
432 CORBA::UNKNOWN ex(UNKNOWN_UserException,
433 (CORBA::CompletionStatus) completion());
434 setServerDeadline(this);
435 impl()->sendSystemException(this,ex);
436 }
437 }
438 pd_state = ReplyCompleted;
439
440 clearValueTracker();
441 clearDeadline();
442 return 1;
443 }
444
445 ////////////////////////////////////////////////////////////////////////
446 CORBA::Boolean
handleLocateRequest()447 GIOP_S::handleLocateRequest() {
448 try {
449
450 impl()->unmarshalLocateRequest(this);
451
452 pd_state = RequestIsBeingProcessed;
453
454 // Here we notify the giopServer that this thread has finished
455 // reading the request. The server may want to keep a watch on
456 // any more request coming in on the connection while this
457 // thread does the upcall.
458
459 CORBA::Boolean data_in_buffer = 0;
460 if (pd_rdlocked) {
461 // This is the thread that is reading from the connection. We
462 // check if we have previously queued giopStream_Buffers on the
463 // connection. In other words, we might have previously read
464 // too much stuff out of the connection and these data belong to
465 // other requests. If that is the case, we notify the giopServer
466 // that there are already buffers waiting to be read.
467 giopStrand& s = strand();
468 data_in_buffer = ((s.head) ? 1 : 0);
469 }
470 pd_worker->server()->notifyWkPreUpCall(pd_worker,data_in_buffer);
471
472 impl()->inputMessageEnd(this,0);
473
474 pd_state = WaitingForReply;
475
476 omniORB::logs(10, "Handling a GIOP LOCATE_REQUEST.");
477
478 GIOP::LocateStatusType status = GIOP::UNKNOWN_OBJECT;
479
480 if (keysize() > 0) {
481 CORBA::ULong hash = omni::hash(key(), keysize());
482 omni_tracedmutex_lock sync(*omni::internalLock);
483 omniLocalIdentity* id;
484 id = omniObjTable::locateActive(key(), keysize(), hash, 1);
485 if( id ) status = GIOP::OBJECT_HERE;
486 }
487 if ( status == GIOP::UNKNOWN_OBJECT && keysize() > 0 ) {
488 // We attempt to find the object adapter (activate it if necassary)
489 // and ask it if the object exists, or if it has the *capability*
490 // to activate such an object. ie. is it able to do object loading
491 // on demand?
492
493 omniObjAdapter_var adapter(omniObjAdapter::getAdapter(key(),keysize()));
494 if( adapter && adapter->objectExists(key(),keysize()) )
495 status = GIOP::OBJECT_HERE;
496 }
497 if ( status == GIOP::UNKNOWN_OBJECT &&
498 keysize() == 4 && !memcmp(key(), "INIT", 4) &&
499 omniInitialReferences::is_bootstrap_agentImpl_initialised() ) {
500 status = GIOP::OBJECT_HERE;
501 }
502
503 setServerDeadline(this);
504 impl()->sendLocateReply(this,status,CORBA::Object::_nil(),0);
505 }
506 catch (omniORB::LOCATION_FORWARD& lf) {
507 CORBA::Object_var release_it(lf.get_obj());
508 setServerDeadline(this);
509 impl()->sendLocateReply(this,
510 lf.is_permanent() ? GIOP::OBJECT_FORWARD_PERM :
511 GIOP::OBJECT_FORWARD,
512 release_it,0);
513 }
514
515 #define MARSHAL_SYSTEM_EXCEPTION() do { \
516 setServerDeadline(this); \
517 if (pd_state == RequestIsBeingProcessed) { \
518 SkipRequestBody(); \
519 } \
520 if (pd_state == WaitForRequestHeader || \
521 pd_state == RequestHeaderIsBeingProcessed) { \
522 impl()->sendMsgErrorMessage(this, &ex); \
523 return 0; \
524 } else if (response_expected()) { \
525 impl()->sendSystemException(this,ex); \
526 } \
527 } while (0)
528
529 # ifndef HAS_Cplusplus_catch_exception_by_base
530
531 // We have to catch each type of system exception separately
532 // here to support compilers which cannot catch more derived
533 // types.
534 # define CATCH_AND_MARSHAL(name) \
535 catch (CORBA::name& ex) { \
536 MARSHAL_SYSTEM_EXCEPTION(); \
537 }
538
539 OMNIORB_FOR_EACH_SYS_EXCEPTION(CATCH_AND_MARSHAL)
540
541 # undef CATCH_AND_MARSHAL
542 #endif
543
544 catch(CORBA::SystemException& ex) {
545 MARSHAL_SYSTEM_EXCEPTION();
546 }
547
548 pd_state = ReplyCompleted;
549
550 clearValueTracker();
551 clearDeadline();
552 return 1;
553 }
554
555 ////////////////////////////////////////////////////////////////////////
556 CORBA::Boolean
handleCancelRequest()557 GIOP_S::handleCancelRequest() {
558 // We do not have the means to asynchronously abort the execution of
559 // an upcall by another thread. Therefore it is not possible to
560 // cancel a request that has already been in progress. The best we
561 // can do is prevent the reply from happening.
562 omniORB::logs(5, "Received a CancelRequest message.");
563 pd_state = WaitingForReply;
564 response_expected(0);
565 clearDeadline();
566 return 1;
567 }
568
569 ////////////////////////////////////////////////////////////////////////
570 void
ReceiveRequest(omniCallDescriptor & desc)571 GIOP_S::ReceiveRequest(omniCallDescriptor& desc) {
572
573 OMNIORB_ASSERT(pd_state == RequestIsBeingProcessed);
574
575 calldescriptor(&desc);
576
577 // When a user exception is throw by the stub code, the
578 // call descriptor could have been deallocated before the
579 // catch frame for the user exception is reached. Therefore
580 // we store the user exception signatures inside our own
581 // private states.
582 pd_n_user_excns = desc.n_user_excns();
583 pd_user_excns = desc.user_excns();
584
585 cdrStream& s = *this;
586 desc.unmarshalArguments(s);
587 pd_state = WaitingForReply;
588
589 clearValueTracker();
590
591 // Here we notify the giopServer that this thread has finished
592 // reading the request. The server may want to keep a watch on
593 // any more request coming in on the connection while this
594 // thread does the upcall.
595
596 CORBA::Boolean data_in_buffer = 0;
597 if (pd_rdlocked) {
598 // This is the thread that is reading from the connection. We
599 // check if we have previously queued giopStream_Buffers on the
600 // connection. In other words, we might have previously read
601 // too much stuff out of the connection and these data belong to
602 // other requests. If that is the case, we notify the giopServer
603 // that there are already buffers waiting to be read.
604 giopStrand& s = strand();
605 data_in_buffer = ((s.head) ? 1 : 0);
606 }
607 pd_worker->server()->notifyWkPreUpCall(pd_worker,data_in_buffer);
608
609 impl()->inputMessageEnd(this,0);
610
611
612 // Check if this call comes in from a bidirectional connection.
613 // If so check if the servant's POA policy allows this.
614 giopStrand& g = strand();
615 if (g.isBiDir() && g.isClient()) {
616 if (!(pd_calldescriptor->poa() &&
617 pd_calldescriptor->poa()->acceptBiDirectional())) {
618 OMNIORB_THROW(OBJ_ADAPTER,OBJ_ADAPTER_BiDirNotAllowed,
619 CORBA::COMPLETED_NO);
620 }
621 }
622 }
623
624 ////////////////////////////////////////////////////////////////////////
625 void
SkipRequestBody()626 GIOP_S::SkipRequestBody() {
627
628 OMNIORB_ASSERT(pd_state == RequestIsBeingProcessed);
629
630 pd_state = WaitingForReply;
631
632 CORBA::Boolean data_in_buffer = 0;
633 if (pd_rdlocked) {
634 giopStrand& s = strand();
635 data_in_buffer = ((s.head) ? 1 : 0);
636 }
637 pd_worker->server()->notifyWkPreUpCall(pd_worker,data_in_buffer);
638
639 impl()->inputMessageEnd(this,1);
640 }
641
642 ////////////////////////////////////////////////////////////////////////
643 void
SendReply()644 GIOP_S::SendReply() {
645
646 OMNIORB_ASSERT(pd_state == WaitingForReply);
647
648 if (!response_expected()) {
649 pd_state = ReplyCompleted;
650 clearDeadline();
651 return;
652 }
653
654 pd_service_contexts.length(0);
655
656 setServerDeadline(this);
657
658 if (omniInterceptorP::serverSendReply) {
659 omniInterceptors::serverSendReply_T::info_T info(*this);
660 omniInterceptorP::visit(info);
661 }
662 pd_state = ReplyIsBeingComposed;
663 impl()->outputMessageBegin(this,impl()->marshalReplyHeader);
664 cdrStream& s = *this;
665 calldescriptor()->marshalReturnedValues(s);
666 impl()->outputMessageEnd(this);
667 pd_state = ReplyCompleted;
668
669 clearValueTracker();
670 clearDeadline();
671 }
672
673 ////////////////////////////////////////////////////////////////////////
674 void
SendException(CORBA::Exception * ex)675 GIOP_S::SendException(CORBA::Exception* ex) {
676
677 OMNIORB_ASSERT(pd_state == WaitingForReply);
678
679 if (!response_expected()) throw terminateProcessing();
680
681 setServerDeadline(this);
682
683 int idsize;
684 const char* repoid = ex->_NP_repoId(&idsize);
685
686 # define TEST_AND_MARSHAL_SYSEXCEPTION(name) \
687 if ( strcmp("IDL:omg.org/CORBA/" #name ":1.0",repoid) == 0 ) { \
688 impl()->sendSystemException(this,*((CORBA::SystemException*)ex)); \
689 pd_state = ReplyCompleted; \
690 return; \
691 }
692
693 OMNIORB_FOR_EACH_SYS_EXCEPTION(TEST_AND_MARSHAL_SYSEXCEPTION)
694 # undef TEST_AND_MARSHAL_SYSEXCEPTION
695
696 // this is not a system exception, treat it as a user exception
697 // we do not check if this is a valid user exception for this operation.
698 // caller should have checked this or else the user exception should have
699 // been thrown as a C++ exception and got handled by the catch clause in
700 // handleRequest.
701 impl()->sendUserException(this,*((CORBA::UserException*)ex));
702 pd_state = ReplyCompleted;
703
704 clearValueTracker();
705 clearDeadline();
706 }
707
708 ////////////////////////////////////////////////////////////////////////
709 void
notifyCommFailure(CORBA::Boolean,CORBA::ULong & minor,CORBA::Boolean & retry)710 GIOP_S::notifyCommFailure(CORBA::Boolean,
711 CORBA::ULong& minor,
712 CORBA::Boolean& retry) {
713 retry = 0;
714
715 if (pd_state == WaitForRequestHeader ||
716 pd_state == RequestIsBeingProcessed) {
717 minor = COMM_FAILURE_UnMarshalArguments;
718 }
719 else if (pd_state == WaitingForReply) {
720 minor = COMM_FAILURE_WaitingForReply;
721 }
722 else if (pd_state == ReplyIsBeingComposed) {
723 minor = COMM_FAILURE_MarshalResults;
724 }
725 else {
726 minor = TRANSIENT_ConnectionClosed;
727 }
728 }
729
730 ////////////////////////////////////////////////////////////////////////
731 CORBA::ULong
completion()732 GIOP_S::completion() {
733 if (pd_state == WaitingForReply) {
734 return (CORBA::ULong)CORBA::COMPLETED_MAYBE;
735 }
736 else if (pd_state == ReplyIsBeingComposed) {
737 return (CORBA::ULong)CORBA::COMPLETED_YES;
738 }
739 else {
740 return (CORBA::ULong)CORBA::COMPLETED_NO;
741 }
742 }
743
744 ////////////////////////////////////////////////////////////////////////
745 const char*
operation_name() const746 GIOP_S::operation_name() const {
747 return operation();
748 }
749
750 ////////////////////////////////////////////////////////////////////////
751 void
unmarshalIORAddressingInfo()752 GIOP_S::unmarshalIORAddressingInfo() {
753 GIOP::AddressingDisposition vp;
754 CORBA::ULong vl;
755
756 resetKey();
757
758 cdrStream& s = *this;
759
760 vp <<= s;
761 if (vp == GIOP::KeyAddr) {
762 vl <<= s;
763 if (!s.checkInputOverrun(1,vl)) {
764 OMNIORB_THROW(MARSHAL,MARSHAL_SequenceIsTooLong,
765 (CORBA::CompletionStatus)completion());
766 }
767 keysize((int)vl);
768 s.get_octet_array(key(),vl);
769 }
770 else {
771
772 GIOP::IORAddressingInfo& ta = pd_target_address;
773 if (vp == GIOP::ProfileAddr) {
774 ta.ior.profiles.length(1);
775 ta.ior.profiles[0] <<= s;
776 ta.selected_profile_index = 0;
777 }
778 else {
779 // GIOP::ReferenceAddr
780 ta.selected_profile_index <<= s;
781 ta.ior <<= s;
782 }
783 if (ta.selected_profile_index >= ta.ior.profiles.length() ||
784 ta.ior.profiles[ta.selected_profile_index].tag !=
785 IOP::TAG_INTERNET_IOP) {
786 if ( omniORB::trace(25) ) {
787 omniORB::logger l;
788 l << "unmarshal corrupted targetAddress at "
789 << __FILE__ << " line no. " << __LINE__ << "\n";
790 }
791 OMNIORB_THROW(BAD_PARAM,BAD_PARAM_IndexOutOfRange,
792 (CORBA::CompletionStatus)completion());
793 }
794
795 IIOP::ProfileBody decodedBody;
796 IIOP::unmarshalProfile(ta.ior.profiles[ta.selected_profile_index],
797 decodedBody);
798
799 #if 0 // XXX Not finalise yet
800 _OMNI_NS(giopAddressList) addresses;
801 IIOP::extractAddresses(decodedBody,addresses);
802 if ( isLocal(addresses) ) {
803 keysize((int)decodedBody.object_key.length());
804 memcpy((void*)key(),decodedBody.object_key.get_buffer(),keysize());
805 }
806 // XXX delete all the addresses.
807 #else
808 OMNIORB_ASSERT(0);
809 #endif
810
811 // Reach here either we have got the key of the target object
812 // or we have the target address info in targetAddress().
813 //
814 if (keysize() < 0) {
815 // We couldn't decode the target address to a local object key. Unless
816 // an interceptor can decode it further, this request will be rejected.
817 if ( omniORB::trace(25) ) {
818 omniORB::logger l;
819 l << "ProfileAddr or ReferenceAddr addresses unknown target at "
820 << __FILE__ << " line no. " << __LINE__ << "\n";
821 }
822 }
823 }
824
825 }
826
827 OMNI_NAMESPACE_END(omni)
828