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