GIOP_Message_Lite.cpp

Go to the documentation of this file.
00001 //GIOP_Message_Lite.cpp,v 1.94 2006/04/20 12:37:17 jwillemsen Exp
00002 
00003 #include "tao/GIOP_Message_Lite.h"
00004 #include "tao/debug.h"
00005 #include "tao/TAOC.h"
00006 #include "tao/ORB_Core.h"
00007 #include "tao/operation_details.h"
00008 #include "tao/TAO_Server_Request.h"
00009 #include "tao/GIOP_Message_Locate_Header.h"
00010 #include "tao/LF_Strategy.h"
00011 #include "tao/Transport.h"
00012 #include "tao/Transport_Mux_Strategy.h"
00013 #include "tao/Codeset_Manager.h"
00014 #include "tao/SystemException.h"
00015 
00016 ACE_RCSID (tao,
00017            GIOP_Message_Lite,
00018            "GIOP_Message_Lite.cpp,v 1.94 2006/04/20 12:37:17 jwillemsen Exp")
00019 
00020 
00021 static const size_t TAO_GIOP_LITE_HEADER_LEN = 5;
00022 static const size_t TAO_GIOP_LITE_MESSAGE_SIZE_OFFSET = 0;
00023 static const size_t TAO_GIOP_LITE_MESSAGE_TYPE_OFFSET = 4;
00024 
00025 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00026 
00027 TAO_GIOP_Message_Lite::TAO_GIOP_Message_Lite (TAO_ORB_Core *orb_core,
00028                                               size_t /*input_cdr_size*/)
00029   : orb_core_ (orb_core),
00030     message_type_ (0),
00031     message_size_ (0),
00032     byte_order_ (TAO_ENCAP_BYTE_ORDER)
00033 {
00034 }
00035 
00036 
00037 TAO_GIOP_Message_Lite::~TAO_GIOP_Message_Lite (void)
00038 {
00039 }
00040 
00041 
00042 void
00043 TAO_GIOP_Message_Lite::init (CORBA::Octet,
00044                              CORBA::Octet)
00045 {
00046   return;
00047 }
00048 
00049 TAO_OutputCDR &
00050 TAO_GIOP_Message_Lite::out_stream (void)
00051 {
00052   return this->cdr_;
00053 }
00054 
00055 void
00056 TAO_GIOP_Message_Lite::reset (void)
00057 {
00058   this->message_type_ = 0;
00059   this->message_size_ = 0;
00060 }
00061 
00062 
00063 int
00064 TAO_GIOP_Message_Lite::generate_request_header (
00065     TAO_Operation_Details &op,
00066     TAO_Target_Specification &spec,
00067     TAO_OutputCDR &cdr
00068   )
00069 {
00070   // Write the GIOPLite header first
00071   if (!this->write_protocol_header (TAO_GIOP_REQUEST,
00072                                     cdr))
00073     {
00074       if (TAO_debug_level)
00075         ACE_ERROR ((LM_ERROR,
00076                     ACE_TEXT ("(%P|%t) Error in writing GIOP header \n")));
00077 
00078 
00079       return -1;
00080     }
00081 
00082   // Now call the implementation for the rest of the header
00083   if (!this->write_request_header (op,
00084                                    spec,
00085                                    cdr))
00086     {
00087       if (TAO_debug_level)
00088         ACE_ERROR ((LM_ERROR,
00089                     ACE_TEXT ("(%P|%t) Error in writing request header \n")));
00090 
00091       return -1;
00092     }
00093 
00094   return 0;
00095 
00096 }
00097 
00098 
00099 int
00100 TAO_GIOP_Message_Lite::generate_locate_request_header (
00101     TAO_Operation_Details &op,
00102     TAO_Target_Specification &spec,
00103     TAO_OutputCDR &cdr
00104  )
00105 {
00106   // Write the GIOPLite header first
00107   if (!this->write_protocol_header (TAO_GIOP_LOCATEREQUEST,
00108                                     cdr))
00109     {
00110       if (TAO_debug_level)
00111         {
00112           ACE_ERROR ((LM_ERROR,
00113                       ACE_TEXT ("(%P|%t) Error in writing GIOPLite header \n")));
00114         }
00115 
00116       return -1;
00117     }
00118 
00119   // Now call the implementation for the rest of the header
00120   if (!this->write_locate_request_header (op.request_id (),
00121                                           spec,
00122                                           cdr))
00123     {
00124       if (TAO_debug_level)
00125         ACE_ERROR ((LM_ERROR,
00126                     ACE_TEXT ("(%P|%t) Error in writing locate request header \n")));
00127 
00128       return -1;
00129     }
00130 
00131   return 0;
00132 }
00133 
00134 
00135 int
00136 TAO_GIOP_Message_Lite::generate_reply_header (
00137     TAO_OutputCDR &cdr,
00138     TAO_Pluggable_Reply_Params_Base &params
00139   )
00140 {
00141   // Write the GIOPLite header first
00142   if (!this->write_protocol_header (TAO_GIOP_REPLY,
00143                                     cdr))
00144     {
00145       if (TAO_debug_level)
00146         {
00147           ACE_ERROR ((LM_ERROR,
00148                       ACE_TEXT ("(%P|%t) Error in writing GIOPLite header \n")));
00149         }
00150 
00151       return -1;
00152     }
00153 
00154   // Now call the implementation for the rest of the header
00155   if (!this->write_reply_header (cdr,
00156                                  params))
00157     {
00158       if (TAO_debug_level > 4)
00159         ACE_ERROR ((LM_ERROR,
00160                     ACE_TEXT ("(%P|%t) Error in writing reply header \n")));
00161 
00162       return -1;
00163     }
00164 
00165   return 0;
00166 }
00167 
00168 int
00169 TAO_GIOP_Message_Lite::generate_fragment_header (TAO_OutputCDR & /* cdr */,
00170                                                  CORBA::ULong /* request_id */)
00171 {
00172   // GIOP fragmentation is not supported in GIOP lite.
00173   return 0;
00174 }
00175 
00176 int
00177 TAO_GIOP_Message_Lite::format_message (TAO_OutputCDR &stream)
00178 {
00179   // Get the header length
00180   const size_t header_len = TAO_GIOP_LITE_HEADER_LEN;
00181 
00182   // Get the message size offset
00183   const size_t offset = TAO_GIOP_LITE_MESSAGE_SIZE_OFFSET;
00184 
00185   // Ptr to first buffer.
00186   char *buf = (char *) stream.buffer ();
00187 
00188   // Length of all buffers.
00189   size_t total_len =
00190     stream.total_length ();
00191 
00192   // NOTE: Here would also be a fine place to calculate a digital
00193   // signature for the message and place it into a preallocated slot
00194   // in the "ServiceContext".  Similarly, this is a good spot to
00195   // encrypt messages (or just the message bodies) if that's needed in
00196   // this particular environment and that isn't handled by the
00197   // networking infrastructure (e.g., IPSEC).
00198 
00199   CORBA::ULong bodylen = static_cast <CORBA::ULong> (total_len - header_len);
00200 
00201 #if !defined (ACE_ENABLE_SWAP_ON_WRITE)
00202   *(reinterpret_cast <CORBA::ULong *> (buf + offset)) = bodylen;
00203 #else
00204   if (!stream.do_byte_swap ())
00205     *(reinterpret_cast <CORBA::ULong *>
00206                            (buf + offset)) = bodylen;
00207   else
00208     ACE_CDR::swap_4 (reinterpret_cast <char *> (&bodylen),
00209                      buf + offset);
00210 #endif /* ACE_ENABLE_SWAP_ON_WRITE */
00211 
00212   // Strictly speaking, should not need to loop here because the
00213   // socket never gets set to a nonblocking mode ... some Linux
00214   // versions seem to need it though.  Leaving it costs little.
00215   if (TAO_debug_level > 2)
00216     {
00217       // Check whether the output cdr stream is build up of multiple
00218       // messageblocks. If so, consolidate them to one block that can be
00219       // dumped
00220       ACE_Message_Block* consolidated_block = 0;
00221       if (stream.begin()->cont() != 0)
00222         {
00223           consolidated_block = new ACE_Message_Block;
00224           ACE_CDR::consolidate(consolidated_block, stream.begin());
00225           buf = (char *) (consolidated_block->rd_ptr ());
00226         }
00227       ///
00228 
00229       this->dump_msg ("send",
00230                       reinterpret_cast <u_char *> (buf),
00231                       stream.length ());
00232 
00233       //
00234       delete consolidated_block;
00235       consolidated_block = 0;
00236       //
00237     }
00238 
00239   return 0;
00240 }
00241 
00242 
00243 int
00244 TAO_GIOP_Message_Lite::parse_incoming_messages (ACE_Message_Block &block)
00245 {
00246   this->reset ();
00247 
00248   // Make sure we have enough bytes in the header to read all
00249   // of the information.
00250   if (block.length () < TAO_GIOP_LITE_HEADER_LEN)
00251     {
00252       return 1;
00253     }
00254 
00255     // Get the read pointer
00256   char *rd_ptr = block.rd_ptr ();
00257 
00258   // We don't need to do this sort of copy. But some compilers (read it
00259   // as SunCC) have a problem in deferencing from the
00260   // reinterpret_cast pointer of the <rd_ptr>, as the <rd_ptr> can be
00261   // on stack. So let us go ahead with this copying...
00262   char buf [4];
00263   buf[0] = *rd_ptr;
00264   buf[1] = *(rd_ptr + 1);
00265   buf[2] = *(rd_ptr + 2);
00266   buf[3] = *(rd_ptr + 3);
00267 
00268   CORBA::ULong x = 0;
00269 #if !defined (ACE_DISABLE_SWAP_ON_READ)
00270   if (!(this->byte_order_ != TAO_ENCAP_BYTE_ORDER))
00271     {
00272       x = *(reinterpret_cast <ACE_CDR::ULong*> (buf));
00273     }
00274   else
00275     {
00276       ACE_CDR::swap_4 (buf, reinterpret_cast <char*> (&x));
00277     }
00278 #else
00279   x = *(reinterpret_cast <ACE_CDR::ULong*> (buf));
00280 #endif /* ACE_DISABLE_SWAP_ON_READ */
00281 
00282   this->message_size_ = x;
00283 
00284   // Get the message type.
00285   this->message_type_ = rd_ptr[TAO_GIOP_LITE_MESSAGE_TYPE_OFFSET];
00286 
00287   return 0;
00288 }
00289 
00290 TAO_Pluggable_Message_Type
00291 TAO_GIOP_Message_Lite::message_type (void) const
00292 {
00293   switch (this->message_type_)
00294     {
00295     case TAO_GIOP_REQUEST:
00296       return TAO_PLUGGABLE_MESSAGE_REQUEST;
00297     case TAO_GIOP_LOCATEREQUEST:
00298       return TAO_PLUGGABLE_MESSAGE_LOCATEREQUEST;
00299 
00300     case TAO_GIOP_LOCATEREPLY:
00301       return TAO_PLUGGABLE_MESSAGE_LOCATEREPLY;
00302     case TAO_GIOP_REPLY:
00303       return TAO_PLUGGABLE_MESSAGE_REPLY;
00304 
00305     case TAO_GIOP_CLOSECONNECTION:
00306       return TAO_PLUGGABLE_MESSAGE_CLOSECONNECTION;
00307 
00308     case TAO_GIOP_CANCELREQUEST:
00309       return TAO_PLUGGABLE_MESSAGE_CANCELREQUEST;
00310 
00311     case TAO_GIOP_MESSAGERROR:
00312     case TAO_GIOP_FRAGMENT:
00313       // Never happens: why??
00314     default:
00315         ACE_ERROR ((LM_ERROR,
00316                     ACE_TEXT ("TAO (%P|%t) %N:%l        message_type : ")
00317                     ACE_TEXT ("wrong message.\n")));
00318     }
00319 
00320   // In case of some errors
00321   return TAO_PLUGGABLE_MESSAGE_MESSAGERROR;
00322 }
00323 
00324 int
00325 TAO_GIOP_Message_Lite::parse_next_message (ACE_Message_Block &incoming,
00326                                            TAO_Queued_Data &qd,
00327                                            size_t &mesg_length)
00328 {
00329   if (incoming.length () < TAO_GIOP_LITE_HEADER_LEN)
00330     {
00331       qd.missing_data_ = TAO_MISSING_DATA_UNDEFINED;
00332 
00333       return 0; /* incomplete header */
00334     }
00335   else
00336     {
00337       if (this->parse_incoming_messages (incoming) == -1)
00338     {
00339       return -1;
00340      }
00341 
00342       const size_t total_len =
00343         this->message_size_ + TAO_GIOP_LITE_HEADER_LEN;
00344 
00345       if (total_len > incoming.length ())
00346         {
00347           qd.missing_data_ = total_len - incoming.length ();
00348         }
00349       else
00350         {
00351           qd.missing_data_ = 0;
00352         }
00353 
00354       this->init_queued_data (&qd);
00355 
00356       mesg_length  = TAO_GIOP_LITE_HEADER_LEN + this->message_size_;
00357 
00358       return 1; /* parsed header successfully */
00359     }
00360 }
00361 
00362 int
00363 TAO_GIOP_Message_Lite::extract_next_message (ACE_Message_Block &incoming,
00364                                              TAO_Queued_Data *&qd)
00365 {
00366   if (incoming.length () < TAO_GIOP_LITE_HEADER_LEN)
00367     {
00368       if (incoming.length () > 0)
00369         {
00370           // Make a node which has a message block of the size of
00371           // MESSAGE_HEADER_LEN.
00372           qd =
00373             this->make_queued_data (TAO_GIOP_LITE_HEADER_LEN);
00374 
00375           if (qd == 0)
00376             {
00377               return -1; /* out of memory */
00378             }
00379 
00380             qd->msg_block_->copy (incoming.rd_ptr (),
00381                                   incoming.length ());
00382           qd->missing_data_ = TAO_MISSING_DATA_UNDEFINED;
00383         }
00384       return 0;
00385     }
00386 
00387   if (this->parse_incoming_messages (incoming) == -1)
00388     {
00389       return -1;
00390     }
00391 
00392   size_t copying_len =
00393     this->message_size_ + TAO_GIOP_LITE_HEADER_LEN;
00394 
00395   qd = this->make_queued_data (copying_len);
00396 
00397   if (qd == 0)
00398     {
00399       return -1; /* out of memory */
00400     }
00401 
00402   if (copying_len > incoming.length ())
00403     {
00404       qd->missing_data_ = copying_len - incoming.length ();
00405 
00406       copying_len = incoming.length ();
00407     }
00408   else
00409     {
00410       qd->missing_data_ = 0;
00411     }
00412 
00413   qd->msg_block_->copy (incoming.rd_ptr (),
00414                         copying_len);
00415 
00416   incoming.rd_ptr (copying_len);
00417   this->init_queued_data (qd);
00418 
00419   return 1;
00420 }
00421 
00422 int
00423 TAO_GIOP_Message_Lite::consolidate_node (TAO_Queued_Data *qd,
00424                                          ACE_Message_Block &incoming)
00425 {
00426   // Look to see whether we had atleast parsed the GIOP header ...
00427   if (qd->missing_data_ == TAO_MISSING_DATA_UNDEFINED)
00428     {
00429       // The data length that has been stuck in there during the last
00430       // read ....
00431       size_t len =
00432         qd->msg_block_->length ();
00433 
00434       // We know that we would have space for
00435       // TAO_GIOP_MESSAGE_HEADER_LEN here.  So copy that much of data
00436       // from the <incoming> into the message block in <qd>
00437       const size_t available     = incoming.length ();
00438       const size_t desired       = TAO_GIOP_LITE_HEADER_LEN - len;
00439       const size_t n_copy        = ace_min (available, desired);
00440 
00441       // paranoid check, but would cause endless loop
00442       if (n_copy == 0)
00443         {
00444           return -1;
00445         }
00446 
00447       qd->msg_block_->copy (incoming.rd_ptr (), n_copy);
00448 
00449       // Move the rd_ptr () in the incoming message block..
00450       incoming.rd_ptr (n_copy);
00451 
00452       // verify there is now enough data to parse the header
00453       if (qd->msg_block_->length () < TAO_GIOP_LITE_HEADER_LEN)
00454         {
00455           return 0;
00456         }
00457 
00458       // Parse the message header now...
00459       if (this->parse_incoming_messages (*qd->msg_block_) == -1)
00460         return -1;
00461 
00462       // Now grow the message block so that we can copy the rest of
00463       // the data...
00464       if (ACE_CDR::grow (qd->msg_block_,
00465                      this->message_size_ + TAO_GIOP_LITE_HEADER_LEN) == -1)
00466         {
00467           /* memory allocation failed */
00468           return -1;
00469         }
00470 
00471       // Copy the pay load..
00472 
00473       // Calculate the bytes that needs to be copied in the queue...
00474       size_t copy_len = this->message_size_;
00475 
00476       // If the data that needs to be copied is more than that is
00477       // available to us ..
00478       if (copy_len > incoming.length ())
00479         {
00480           // Calculate the missing data..
00481           qd->missing_data_ = copy_len - incoming.length ();
00482 
00483           // Set the actual possible copy_len that is available...
00484           copy_len = incoming.length ();
00485         }
00486       else
00487         {
00488           qd->missing_data_ = 0;
00489         }
00490 
00491       // paranoid check
00492       if (copy_len == 0)
00493         {
00494           return -1;
00495         }
00496 
00497       // ..now we are set to copy the right amount of data to the
00498       // node..
00499       qd->msg_block_->copy (incoming.rd_ptr (),
00500                             copy_len);
00501 
00502       // Set the <rd_ptr> of the <incoming>..
00503       incoming.rd_ptr (copy_len);
00504 
00505       // Get the other details...
00506       this->init_queued_data (qd);
00507     }
00508   else
00509     {
00510       // @@todo: Need to abstract this out to a seperate method...
00511       size_t copy_len = qd->missing_data_;
00512 
00513       if (copy_len > incoming.length ())
00514         {
00515           // Calculate the missing data..
00516           qd->missing_data_ = copy_len - incoming.length ();
00517 
00518           // Set the actual possible copy_len that is available...
00519           copy_len = incoming.length ();
00520         }
00521 
00522       // Copy the right amount of data in to the node...
00523       // node..
00524       qd->msg_block_->copy (incoming.rd_ptr (),
00525                             copy_len);
00526 
00527       // Set the <rd_ptr> of the <incoming>..
00528       qd->msg_block_->rd_ptr (copy_len);
00529 
00530     }
00531 
00532   return 0;
00533 }
00534 
00535 int
00536 TAO_GIOP_Message_Lite::process_request_message (TAO_Transport *transport,
00537                                                 TAO_Queued_Data *qd)
00538 {
00539   // Set the upcall thread
00540   this->orb_core_->lf_strategy ().set_upcall_thread (
00541       this->orb_core_->leader_follower ());
00542 
00543   // A buffer that we will use to initialise the CDR stream
00544   char repbuf[ACE_CDR::DEFAULT_BUFSIZE];
00545 
00546 #if defined(ACE_INITIALIZE_MEMORY_BEFORE_USE)
00547   (void) ACE_OS::memset (repbuf,
00548                          '\0',
00549                          sizeof repbuf);
00550 #endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
00551 
00552   // Initialze an output CDR on the stack
00553   TAO_OutputCDR output (repbuf,
00554                         sizeof repbuf,
00555                         TAO_ENCAP_BYTE_ORDER,
00556                         this->orb_core_->output_cdr_buffer_allocator (),
00557                         this->orb_core_->output_cdr_dblock_allocator (),
00558                         this->orb_core_->output_cdr_msgblock_allocator (),
00559                         this->orb_core_->orb_params ()->cdr_memcpy_tradeoff (),
00560                         qd->major_version_,
00561                         qd->minor_version_);
00562 
00563   transport->assign_translators(0,&output);
00564 
00565   // Get the read and write positions before we steal data.
00566   size_t rd_pos = qd->msg_block_->rd_ptr () - qd->msg_block_->base ();
00567   size_t wr_pos = qd->msg_block_->wr_ptr () - qd->msg_block_->base ();
00568   rd_pos += TAO_GIOP_LITE_HEADER_LEN;
00569 
00570   if (TAO_debug_level > 0)
00571     this->dump_msg ("recv",
00572                     reinterpret_cast <u_char *> (qd->msg_block_->rd_ptr ()),
00573                     qd->msg_block_->length ());
00574 
00575 
00576   // Create a input CDR stream.
00577   // NOTE: We use the same data block in which we read the message and
00578   // we pass it on to the higher layers of the ORB. So we dont to any
00579   // copies at all here. The same is also done in the higher layers.
00580 
00581   TAO_InputCDR input_cdr (qd->msg_block_->data_block (),
00582                           ACE_Message_Block::DONT_DELETE,
00583                           rd_pos,
00584                           wr_pos,
00585                           qd->byte_order_,
00586                           qd->major_version_,
00587                           qd->minor_version_,
00588                           this->orb_core_);
00589 
00590 
00591   // We know we have some request message. Check whether it is a
00592   // GIOP_REQUEST or GIOP_LOCATE_REQUEST to take action.
00593   switch (qd->msg_type_)
00594     {
00595     case TAO_PLUGGABLE_MESSAGE_REQUEST:
00596       // Should be taken care by the state specific invocations. They
00597       // could raise an exception or write things in the output CDR
00598       // stream
00599       return this->process_request (transport,
00600                                     input_cdr,
00601                                     output);
00602     case TAO_PLUGGABLE_MESSAGE_LOCATEREQUEST:
00603       return this->process_locate_request (transport,
00604                                            input_cdr,
00605                                            output);
00606     default:
00607       return -1;
00608     }
00609 }
00610 
00611 int
00612 TAO_GIOP_Message_Lite::process_reply_message (
00613     TAO_Pluggable_Reply_Params &params,
00614     TAO_Queued_Data *qd
00615   )
00616 {
00617 
00618 
00619   // Get the read and write positions before we steal data.
00620   size_t rd_pos = qd->msg_block_->rd_ptr () - qd->msg_block_->base ();
00621   size_t wr_pos = qd->msg_block_->wr_ptr () - qd->msg_block_->base ();
00622   rd_pos += TAO_GIOP_LITE_HEADER_LEN;
00623 
00624   if (TAO_debug_level > 0)
00625     this->dump_msg ("recv",
00626                     reinterpret_cast <u_char *> (qd->msg_block_->rd_ptr ()),
00627                     qd->msg_block_->length ());
00628 
00629 
00630   // Create a empty buffer on stack
00631   // NOTE: We use the same data block in which we read the message and
00632   // we pass it on to the higher layers of the ORB. So we dont to any
00633   // copies at all here. The same is also done in the higher layers.
00634   TAO_InputCDR input_cdr (qd->msg_block_->data_block (),
00635                           ACE_Message_Block::DONT_DELETE,
00636                           rd_pos,
00637                           wr_pos,
00638                           qd->byte_order_,
00639                           qd->major_version_,
00640                           qd->minor_version_,
00641                           this->orb_core_);
00642 
00643   // Reset the message state. Now, we are ready for the next nested
00644   // upcall if any.
00645   // this->message_handler_.reset (0);
00646 
00647   // We know we have some reply message. Check whether it is a
00648   // GIOP_REPLY or GIOP_LOCATE_REPLY to take action.
00649 
00650   // Once we send the InputCDR stream we need to just forget about
00651   // the stream and never touch that again for anything. We basically
00652   // loose ownership of the data_block.
00653 
00654   // We know we have some reply message. Check whether it is a
00655   // GIOP_REPLY or GIOP_LOCATE_REPLY to take action.
00656   switch (qd->msg_type_)
00657     {
00658     case TAO_PLUGGABLE_MESSAGE_REPLY:
00659       // Should be taken care by the state specific parsing
00660       return this->parse_reply (input_cdr,
00661                                 params);
00662     case TAO_PLUGGABLE_MESSAGE_LOCATEREPLY:
00663       // We call parse_reply () here because, the message format for
00664       // the LOCATEREPLY & REPLY are same.
00665       return this->parse_reply (input_cdr,
00666                                 params);
00667     default:
00668       return -1;
00669     }
00670 }
00671 
00672 int
00673 TAO_GIOP_Message_Lite::generate_exception_reply (
00674     TAO_OutputCDR &cdr,
00675     TAO_Pluggable_Reply_Params_Base &params,
00676     CORBA::Exception &x
00677   )
00678 {
00679   // A new try/catch block, but if something goes wrong now we have no
00680   // hope, just abort.
00681   ACE_DECLARE_NEW_CORBA_ENV;
00682 
00683   ACE_TRY
00684     {
00685       // Make the GIOP & reply header. They are version specific.
00686       this->write_reply_header (cdr,
00687                                 params);
00688       x._tao_encode (cdr ACE_ENV_ARG_PARAMETER);
00689       ACE_TRY_CHECK;
00690     }
00691   ACE_CATCH (CORBA::Exception, ex)
00692     {
00693       // Now we know that while handling the error an other error
00694       // happened -> no hope, close connection.
00695 
00696       // Close the handle.
00697       ACE_DEBUG ((LM_DEBUG,
00698                   ACE_TEXT ("(%P|%t|%N|%l) cannot marshal exception, ")
00699                   ACE_TEXT ("generate_exception_reply ()\n")));
00700       return -1;
00701     }
00702   ACE_ENDTRY;
00703   ACE_CHECK_RETURN (-1);
00704 
00705   return 0;
00706 }
00707 
00708 
00709 int
00710 TAO_GIOP_Message_Lite::write_protocol_header (
00711     TAO_GIOP_Message_Type type,
00712     TAO_OutputCDR &msg)
00713 {
00714   // Reset the message type
00715   msg.reset ();
00716 
00717   // @@ Bala: this is something to think harder about:  right now we
00718   // leave the space to store the length, and later we set it, but the
00719   // way we do it is CDR specific...  Maybe the XXXStream classes
00720   // should support a 'save your current position' method that returns
00721   // a 'Mememto' (check the GoF book), later the CDR stream could be
00722   // restored to that state, and the size written to it.
00723   // @@ Then again, i don't know how would that work with fragments
00724   // (eventually we may want TAO to generate fragments), or protocols
00725   // based on chunking....
00726   //
00727   // Write a dummy <size> later it is set to the right value...  @@
00728   CORBA::ULong size = 0;
00729   msg.write_ulong (size);
00730 
00731   msg.write_octet ((CORBA::Octet) type);
00732 
00733   return 1;
00734 }
00735 
00736 
00737 int
00738 TAO_GIOP_Message_Lite::process_request (TAO_Transport *transport,
00739                                         TAO_InputCDR &cdr,
00740                                         TAO_OutputCDR &output)
00741 {
00742   // This will extract the request header, set <response_required>
00743   // and <sync_with_server> as appropriate.
00744   TAO_ServerRequest request (this,
00745                              cdr,
00746                              output,
00747                              transport,
00748                              this->orb_core_);
00749 
00750   CORBA::ULong request_id = 0;
00751   CORBA::Boolean response_required = 0;
00752 
00753   int parse_error = 0;
00754 
00755   ACE_DECLARE_NEW_CORBA_ENV;
00756   ACE_TRY
00757     {
00758       parse_error =
00759         this->parse_request_header (request);
00760 
00761       TAO_Codeset_Manager *csm = request.orb_core()->codeset_manager();
00762       if (csm)
00763         {
00764           csm->process_service_context(request);
00765           transport->assign_translators(&cdr,&output);
00766         }
00767 
00768       // Throw an exception if the
00769       if (parse_error != 0)
00770         ACE_TRY_THROW (CORBA::MARSHAL (0,
00771                                        CORBA::COMPLETED_NO));
00772       request_id = request.request_id ();
00773 
00774       response_required = request.response_expected ();
00775 
00776       CORBA::Object_var forward_to;
00777 
00778       // Do this before the reply is sent.
00779       this->orb_core_->adapter_registry ()->dispatch (request.object_key (),
00780                                                       request,
00781                                                       forward_to
00782                                                        ACE_ENV_ARG_PARAMETER);
00783       ACE_TRY_CHECK;
00784 
00785       if (!CORBA::is_nil (forward_to.in ()))
00786         {
00787           // We should forward to another object...
00788           TAO_Pluggable_Reply_Params reply_params (transport);
00789           reply_params.request_id_ = request_id;
00790           reply_params.reply_status_ = TAO_GIOP_LOCATION_FORWARD;
00791           reply_params.svc_ctx_.length (0);
00792 
00793           // Send back the reply service context list.
00794           reply_params.service_context_notowned (&request.reply_service_info ());
00795 
00796           // Make the GIOP header and Reply header
00797           this->generate_reply_header (output,
00798                                        reply_params);
00799 
00800           if (!(output << forward_to.in ()))
00801             {
00802               if (TAO_debug_level > 0)
00803                 ACE_ERROR ((LM_ERROR,
00804                             ACE_TEXT ("TAO (%P|%t) ERROR: Unable to marshal ")
00805                             ACE_TEXT ("forward reference.\n")));
00806 
00807               return -1;
00808             }
00809 
00810           int result = transport->send_message (output);
00811           if (result == -1)
00812             {
00813               if (TAO_debug_level > 0)
00814                 {
00815                   // No exception but some kind of error, yet a
00816                   // response is required.
00817                   ACE_ERROR ((LM_ERROR,
00818                               ACE_TEXT ("TAO: (%P|%t|%N|%l) %p: ")
00819                               ACE_TEXT ("cannot send reply\n"),
00820                               ACE_TEXT ("TAO_GIOP_Message_Lite::process_request")));
00821                 }
00822             }
00823           return result;
00824         }
00825     }
00826   // Only CORBA exceptions are caught here.
00827   ACE_CATCHANY
00828     {
00829       int result = 0;
00830 
00831       if (response_required)
00832         {
00833           result = this->send_reply_exception (transport,
00834                                                this->orb_core_,
00835                                                request_id,
00836                                                &request.reply_service_info (),
00837                                                &ACE_ANY_EXCEPTION);
00838           if (result == -1)
00839             {
00840               if (TAO_debug_level > 0)
00841                 {
00842                   ACE_ERROR ((LM_ERROR,
00843                               ACE_TEXT ("TAO: (%P|%t|%N|%l) %p: ")
00844                               ACE_TEXT ("cannot send exception\n"),
00845                               ACE_TEXT ("process_request ()")));
00846                   ACE_PRINT_EXCEPTION (
00847                       ACE_ANY_EXCEPTION,
00848                       "TAO_GIOP_Message_Lite::process_request[2]");
00849                 }
00850             }
00851 
00852         }
00853       else if (TAO_debug_level > 0)
00854         {
00855           // It is unfortunate that an exception (probably a system
00856           // exception) was thrown by the upcall code (even by the
00857           // user) when the client was not expecting a response.
00858           // However, in this case, we cannot close the connection
00859           // down, since it really isn't the client's fault.
00860 
00861           ACE_ERROR ((LM_ERROR,
00862                       ACE_TEXT ("(%P|%t) exception thrown ")
00863                       ACE_TEXT ("but client is not waiting a response\n")));
00864 
00865           ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION,
00866                                "TAO: ");
00867         }
00868 
00869       return result;
00870     }
00871 #if defined (TAO_HAS_EXCEPTIONS)
00872   ACE_CATCHALL
00873     {
00874       // @@ TODO some c++ exception or another, but what do we do with
00875       //    it?
00876       // We are supposed to map it into a CORBA::UNKNOWN exception.
00877       // BTW, this cannot be detected if using the <env> mapping.  If
00878       // we have native exceptions but no support for them in the ORB
00879       // we should still be able to catch it.  If we don't have native
00880       // exceptions it couldn't have been raised in the first place!
00881       int result = 0;
00882 
00883       if (response_required)
00884         {
00885           CORBA::UNKNOWN exception (
00886               CORBA::SystemException::_tao_minor_code (
00887                   TAO_UNHANDLED_SERVER_CXX_EXCEPTION,
00888                   0
00889                 ),
00890               CORBA::COMPLETED_MAYBE
00891             );
00892 
00893           result = this->send_reply_exception (transport,
00894                                                this->orb_core_,
00895                                                request_id,
00896                                                &request.reply_service_info (),
00897                                                &exception);
00898           if (result == -1)
00899             {
00900               if (TAO_debug_level > 0)
00901                 {
00902                   ACE_ERROR ((LM_ERROR,
00903                               ACE_TEXT ("TAO (%P|%t) - TAO_GIOP_Message_Lite::process_request[3], ")
00904                               ACE_TEXT ("%p: ")
00905                               ACE_TEXT ("cannot send exception\n"),
00906                               ACE_TEXT ("process_request ()")));
00907                   ACE_PRINT_EXCEPTION (
00908                       exception,
00909                       "TAO_GIOP_Message_Lite::process_request[3]");
00910                 }
00911             }
00912         }
00913       else if (TAO_debug_level > 0)
00914         {
00915           // It is unfotunate that an exception (probably a system
00916           // exception) was thrown by the upcall code (even by the
00917           // user) when the client was not expecting a response.
00918           // However, in this case, we cannot close the connection
00919           // down, since it really isn't the client's fault.
00920           ACE_ERROR ((LM_ERROR,
00921                       ACE_TEXT ("(%P|%t|%N|%l) exception thrown ")
00922                       ACE_TEXT ("but client is not waiting a response\n")));
00923         }
00924 
00925       return result;
00926     }
00927 #endif /* TAO_HAS_EXCEPTIONS */
00928   ACE_ENDTRY;
00929 
00930   return 0;
00931 }
00932 
00933 
00934 int
00935 TAO_GIOP_Message_Lite::process_locate_request (TAO_Transport *transport,
00936                                                TAO_InputCDR &input,
00937                                                TAO_OutputCDR &output)
00938 {
00939   // This will extract the request header, set <response_required> as
00940   // appropriate.
00941   TAO_GIOP_Locate_Request_Header locate_request (input,
00942                                                  this->orb_core_);
00943 
00944   TAO_GIOP_Locate_Status_Msg status_info;
00945 
00946   // Defaulting.
00947   status_info.status = TAO_GIOP_UNKNOWN_OBJECT;
00948 
00949   CORBA::Boolean response_required = 1;
00950 
00951   ACE_DECLARE_NEW_CORBA_ENV;
00952   ACE_TRY
00953     {
00954       int parse_error =
00955         this->parse_locate_header (locate_request);
00956 
00957       if (parse_error != 0)
00958         {
00959           ACE_TRY_THROW (CORBA::MARSHAL (0,
00960                                          CORBA::COMPLETED_NO));
00961         }
00962 
00963       // Execute a fake request to find out if the object is there or
00964       // if the POA can activate it on demand...
00965       char repbuf[ACE_CDR::DEFAULT_BUFSIZE];
00966       TAO_OutputCDR dummy_output (repbuf,
00967                                   sizeof repbuf);
00968       // This output CDR is not used!
00969 
00970       TAO::ObjectKey tmp_key (locate_request.object_key ().length (),
00971                               locate_request.object_key ().length (),
00972                               locate_request.object_key ().get_buffer (),
00973                               0);
00974 
00975       // Set it to an error state
00976       parse_error = 1;
00977       CORBA::ULong req_id = locate_request.request_id ();
00978 
00979       // We will send the reply. The ServerRequest class need not send
00980       // the reply
00981       CORBA::Boolean deferred_reply = 1;
00982       TAO_ServerRequest server_request (this,
00983                                         req_id,
00984                                         response_required,
00985                                         deferred_reply,
00986                                         tmp_key,
00987                                         "_non_existent",
00988                                         dummy_output,
00989                                         transport,
00990                                         this->orb_core_,
00991                                         parse_error);
00992 
00993       if (parse_error != 0)
00994         {
00995           ACE_TRY_THROW (CORBA::MARSHAL (0,
00996                                          CORBA::COMPLETED_NO));
00997         }
00998 
00999       CORBA::Object_var forward_to;
01000 
01001       this->orb_core_->adapter_registry ()->dispatch (server_request.object_key (),
01002                                                       server_request,
01003                                                       forward_to
01004                                                        ACE_ENV_ARG_PARAMETER);
01005       ACE_TRY_CHECK;
01006 
01007       if (!CORBA::is_nil (forward_to.in ()))
01008         {
01009           status_info.status = TAO_GIOP_OBJECT_FORWARD;
01010           status_info.forward_location_var = forward_to;
01011           ACE_DEBUG ((LM_DEBUG,
01012                       ACE_TEXT ("TAO (%P|%t) - TAO_GIOP_Message_Lite::process_locate_request, ")
01013                       ACE_TEXT ("called: forwarding\n")));
01014         }
01015       else if (server_request.exception_type () == TAO_GIOP_NO_EXCEPTION)
01016         {
01017           // We got no exception, so the object is here.
01018           status_info.status = TAO_GIOP_OBJECT_HERE;
01019           if (TAO_debug_level > 0)
01020             ACE_DEBUG ((LM_DEBUG,
01021                         ACE_TEXT ("TAO (%P|%t) - TAO_GIOP_Message_Lite::process_locate_request, ")
01022                         ACE_TEXT ("found\n")));
01023         }
01024       else
01025         {
01026           status_info.forward_location_var = server_request.forward_location ();
01027 
01028           if (!CORBA::is_nil (status_info.forward_location_var.in ()))
01029             {
01030               status_info.status = TAO_GIOP_OBJECT_FORWARD;
01031               ACE_DEBUG ((LM_DEBUG,
01032                           ACE_TEXT ("TAO (%P|%t) - TAO_GIOP_Message_Lite::process_locate_request, ")
01033                           ACE_TEXT ("forwarding\n")));
01034             }
01035           else
01036             {
01037               // Normal exception, so the object is not here
01038               status_info.status = TAO_GIOP_UNKNOWN_OBJECT;
01039               ACE_DEBUG ((LM_DEBUG,
01040                           ACE_TEXT ("TAO (%P|%t) - TAO_GIOP_Message_Lite::process_locate_request, ")
01041                           ACE_TEXT ("not here\n")));
01042             }
01043         }
01044     }
01045 
01046   ACE_CATCHANY
01047     {
01048       // Normal exception, so the object is not here
01049       status_info.status = TAO_GIOP_UNKNOWN_OBJECT;
01050       if (TAO_debug_level > 0)
01051         ACE_DEBUG ((LM_DEBUG,
01052                     ACE_TEXT ("TAO (%P|%t) TAO_GIOP_Message_Lite::process_locate_request - ")
01053                     ACE_TEXT ("CORBA exception raised\n")));
01054     }
01055 #if defined (TAO_HAS_EXCEPTIONS)
01056   ACE_CATCHALL
01057     {
01058       // Normal exception, so the object is not here
01059       status_info.status = TAO_GIOP_UNKNOWN_OBJECT;
01060       if (TAO_debug_level > 0)
01061         ACE_DEBUG ((LM_DEBUG,
01062                     ACE_TEXT ("TAO (%P|%t) TAO_GIOP_Message_Lite::process_locate_request - ")
01063                     ACE_TEXT ("C++ exception raised\n")));
01064     }
01065 #endif /* TAO_HAS_EXCEPTIONS */
01066   ACE_ENDTRY;
01067 
01068   return this->make_send_locate_reply (transport,
01069                                        output,
01070                                        locate_request,
01071                                        status_info);
01072 }
01073 
01074 
01075 int
01076 TAO_GIOP_Message_Lite::make_send_locate_reply (
01077     TAO_Transport *transport,
01078     TAO_OutputCDR &output,
01079     TAO_GIOP_Locate_Request_Header &request,
01080     TAO_GIOP_Locate_Status_Msg &status_info
01081   )
01082 {
01083   // Note here we are making the Locate reply header which is *QUITE*
01084   // different from the reply header made by the make_reply () call..
01085   // Make the GIOP message header
01086   this->write_protocol_header (TAO_GIOP_LOCATEREPLY,
01087                                output);
01088 
01089   // This writes the header & body
01090   this->write_locate_reply_mesg (output,
01091                                  request.request_id (),
01092                                  status_info);
01093 
01094   // Send the message
01095   int result = transport->send_message (output);
01096 
01097   // Print out message if there is an error
01098   if (result == -1)
01099     {
01100       if (TAO_debug_level > 0)
01101         {
01102           ACE_ERROR ((LM_ERROR,
01103                       ACE_TEXT ("TAO: (%P|%t) %p: cannot send reply\n"),
01104                       ACE_TEXT ("TAO_GIOP_Message_Lite::make_send_locate_reply")));
01105         }
01106     }
01107 
01108   return result;
01109 }
01110 
01111 int
01112 TAO_GIOP_Message_Lite::parse_reply (TAO_InputCDR &cdr,
01113                                     TAO_Pluggable_Reply_Params &params)
01114 {
01115 
01116   // Read the request id
01117   if (!cdr.read_ulong (params.request_id_))
01118     {
01119       if (TAO_debug_level > 0)
01120         {
01121           ACE_DEBUG ((LM_DEBUG,
01122                       ACE_TEXT ("TAO (%P|%t|%N|%l) : ")
01123                       ACE_TEXT ("TAO_GIOP_Message_Lite::parse_reply, ")
01124                       ACE_TEXT ("extracting request id\n")));
01125         }
01126 
01127       return -1;
01128     }
01129 
01130   CORBA::ULong rep_stat = 0;
01131 
01132   // and the reply status type.  status can be NO_EXCEPTION,
01133   // SYSTEM_EXCEPTION, USER_EXCEPTION, LOCATION_FORWARD
01134   // CAnnot handle LOCATION_FORWARD_PERM here
01135   if (!cdr.read_ulong (rep_stat))
01136     {
01137       if (TAO_debug_level > 0)
01138         {
01139           ACE_DEBUG ((LM_DEBUG,
01140                       ACE_TEXT ("TAO (%P|%t|%N|%l) : ")
01141                       ACE_TEXT ("TAO_GIOP_Message_Lite::parse_reply, ")
01142                       ACE_TEXT ("extracting reply status\n")));
01143         }
01144 
01145       return -1;
01146     }
01147 
01148   // Pass the right Pluggable interface code to the transport layer
01149   switch (rep_stat)
01150     {
01151       // Request completed successfully
01152     case TAO_GIOP_NO_EXCEPTION:
01153       params.reply_status_ = TAO_PLUGGABLE_MESSAGE_NO_EXCEPTION;
01154       break;
01155 
01156       // Request terminated with user exception
01157     case TAO_GIOP_USER_EXCEPTION:
01158       params.reply_status_ = TAO_PLUGGABLE_MESSAGE_USER_EXCEPTION;
01159       break;
01160       // Request terminated with system exception
01161     case TAO_GIOP_SYSTEM_EXCEPTION:
01162       params.reply_status_ = TAO_PLUGGABLE_MESSAGE_SYSTEM_EXCEPTION;
01163       break;
01164       // Reply is a location forward type
01165     case TAO_GIOP_LOCATION_FORWARD:
01166       params.reply_status_ = TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD;
01167       break;
01168     default:
01169       if (TAO_debug_level > 0)
01170         {
01171           ACE_DEBUG ((LM_DEBUG,
01172                       ACE_TEXT ("(%N|%l) Unknown reply status \n")));
01173         }
01174     }
01175 
01176   params.input_cdr_= &cdr;
01177 
01178   if ( params.transport_->tms ()->dispatch_reply (params) == -1)
01179     {
01180       // Something really critical happened, we will forget about
01181       // every reply on this connection.
01182       if (TAO_debug_level > 0)
01183         ACE_ERROR ((LM_ERROR,
01184                     "TAO (%P|%t) - GIOP_Message_Lite[%d]::process_parsed_messages, "
01185                     "dispatch reply failed\n",
01186                     params.transport_->id ()));
01187 
01188       return -1;
01189     }
01190 
01191   return 0;
01192 }
01193 
01194 
01195 
01196 int
01197 TAO_GIOP_Message_Lite::write_reply_header (
01198     TAO_OutputCDR &output,
01199     TAO_Pluggable_Reply_Params_Base &reply
01200     ACE_ENV_ARG_DECL_NOT_USED /* ACE_ENV_SINGLE_ARG_PARAMETER */
01201   )
01202     ACE_THROW_SPEC ((CORBA::SystemException))
01203 {
01204   // Write the GIOP Lite header first
01205   this->write_protocol_header (TAO_GIOP_REPLY,
01206                                output);
01207 
01208   // Write the request ID
01209   output.write_ulong (reply.request_id_);
01210 
01211   // Write the reply status
01212   switch (reply.reply_status_)
01213     {
01214     case TAO_PLUGGABLE_MESSAGE_NO_EXCEPTION:
01215       output.write_ulong (TAO_GIOP_NO_EXCEPTION);
01216       break;
01217     case TAO_PLUGGABLE_MESSAGE_LOCATION_FORWARD:
01218       output.write_ulong (TAO_GIOP_LOCATION_FORWARD);
01219       break;
01220     case TAO_PLUGGABLE_MESSAGE_SYSTEM_EXCEPTION:
01221       output.write_ulong (TAO_GIOP_SYSTEM_EXCEPTION);
01222       break;
01223     case TAO_PLUGGABLE_MESSAGE_USER_EXCEPTION:
01224       output.write_ulong (TAO_GIOP_USER_EXCEPTION);
01225       break;
01226     default:
01227       // Some other specifc exception
01228       output.write_ulong (reply.reply_status_);
01229       break;
01230     }
01231 
01232   return 1;
01233 }
01234 
01235 int
01236 TAO_GIOP_Message_Lite::write_request_header (
01237     const TAO_Operation_Details &opdetails,
01238     TAO_Target_Specification &spec,
01239      TAO_OutputCDR &out_stream
01240    )
01241 {
01242   out_stream << opdetails.request_id ();
01243 
01244   const CORBA::Octet response_flags = opdetails.response_flags ();
01245 
01246   // @@ (JP) Temporary hack until all of GIOP 1.2 is implemented.
01247   if (response_flags == TAO_TWOWAY_RESPONSE_FLAG)
01248     {
01249       out_stream << ACE_OutputCDR::from_octet (1);
01250     }
01251   // Sync scope - ignored by server if request is not oneway.
01252   else if (response_flags == CORBA::Octet (Messaging::SYNC_WITH_TRANSPORT)
01253            || response_flags == CORBA::Octet (Messaging::SYNC_NONE)
01254            || response_flags == CORBA::Octet (TAO::SYNC_EAGER_BUFFERING)
01255            || response_flags == CORBA::Octet (TAO::SYNC_DELAYED_BUFFERING))
01256     {
01257       // No response required.
01258       out_stream << ACE_OutputCDR::from_octet (0);
01259     }
01260   else if (response_flags == CORBA::Octet (Messaging::SYNC_WITH_SERVER))
01261     {
01262       // Return before dispatching servant.  We're also setting the high
01263       // bit here. This is a temporary fix until the rest of GIOP 1.2 is
01264       // implemented in TAO.
01265       out_stream << ACE_OutputCDR::from_octet (129);
01266     }
01267   else if (response_flags == CORBA::Octet (Messaging::SYNC_WITH_TARGET))
01268     {
01269       // Return after dispatching servant.
01270       out_stream << ACE_OutputCDR::from_octet (3);
01271     }
01272   else
01273     {
01274       // Until more flags are defined by the OMG.
01275       return 0;
01276     }
01277 
01278   // In this case we cannot recognise anything other than the Object
01279   // key as the address disposition variable. But we do a sanity check
01280   // anyway.
01281   const TAO::ObjectKey *key = spec.object_key ();
01282 
01283   if (key != 0)
01284     {
01285       // Put in the object key
01286       out_stream << *key;
01287     }
01288     else
01289     {
01290       if (TAO_debug_level)
01291         {
01292           ACE_DEBUG ((
01293               LM_DEBUG,
01294               ACE_TEXT ("(%N |%l) Unable to handle this request \n")
01295             ));
01296         }
01297 
01298       return 0;
01299     }
01300 
01301   out_stream.write_string (opdetails.opname_len (),
01302                            opdetails.opname ());
01303 
01304   return 1;
01305 }
01306 
01307 int
01308 TAO_GIOP_Message_Lite::write_locate_request_header (
01309     CORBA::ULong request_id,
01310     TAO_Target_Specification &spec,
01311     TAO_OutputCDR &msg
01312   )
01313 {
01314   msg << request_id;
01315 
01316   // In this case we cannot recognise anything other than the Object
01317   // key as the address disposition variable. But we do a sanity check
01318   // anyway.
01319   const TAO::ObjectKey *key = spec.object_key ();
01320 
01321   if (key)
01322     {
01323       // Put in the object key
01324       msg << *key;
01325     }
01326     else
01327     {
01328       if (TAO_debug_level)
01329         {
01330           ACE_DEBUG ((
01331               LM_DEBUG,
01332               ACE_TEXT ("(%N |%l) Unable to handle this request \n")
01333             ));
01334         }
01335 
01336       return 0;
01337     }
01338 
01339   return 1;
01340 }
01341 
01342 
01343 int
01344 TAO_GIOP_Message_Lite::parse_request_header (TAO_ServerRequest &request)
01345 {
01346   // Get the input CDR in the request class
01347   TAO_InputCDR & input = *request.incoming ();
01348 
01349   CORBA::Boolean hdr_status = (CORBA::Boolean) input.good_bit ();
01350 
01351   CORBA::ULong req_id = 0;
01352 
01353   // Get the rest of the request header ...
01354   hdr_status = hdr_status && input.read_ulong (req_id);
01355 
01356   request.request_id (req_id);
01357 
01358   CORBA::Octet response_flags = CORBA::Octet();
01359   hdr_status = hdr_status && input.read_octet (response_flags);
01360   request.response_expected ((response_flags != 0));
01361 
01362    // The high bit of the octet has been set if the SyncScope policy
01363   // value is SYNC_WITH_SERVER. This is a temporary hack until all
01364   // of GIOP 1.2 is in place. Then we can check the version in the
01365   // message header instead.
01366   request.sync_with_server ((response_flags == 129));
01367 
01368     // We use ad-hoc demarshalling here: there is no need to increase
01369   // the reference count on the CDR message block, because this key
01370   // will not outlive the request (or the message block).
01371   CORBA::Long key_length = 0;
01372   hdr_status = hdr_status && input.read_long (key_length);
01373 
01374   if (hdr_status)
01375     {
01376       request.object_key ().replace (key_length, key_length,
01377                                      (CORBA::Octet*)input.rd_ptr (),
01378                                      0);
01379       input.skip_bytes (key_length);
01380     }
01381 
01382   if (input.char_translator () == 0)
01383     {
01384       CORBA::ULong length = 0;
01385       hdr_status = hdr_status && input.read_ulong (length);
01386 
01387       if (hdr_status)
01388         {
01389           // Do not include NULL character at the end.
01390           // @@ This is not getting demarshaled using the codeset
01391           //    translators!
01392 
01393           // Notice that there are no memory allocations involved
01394           // here!
01395 
01396           request.operation (input.rd_ptr (),
01397                              length - 1,
01398                              0 /* TAO_ServerRequest does NOT own string */);
01399 
01400           hdr_status = input.skip_bytes (length);
01401         }
01402     }
01403   else
01404     {
01405       // @@ We could optimize for this case too, i.e. do in-place
01406       //    demarshaling of the string... But there is an issue
01407       //    pending on the OMG as to whether the operation should be
01408       //    sent in the connection negotiated codeset or always in
01409       //    ISO8859-1.
01410       CORBA::String_var tmp;
01411       hdr_status = hdr_status && input.read_string (tmp.inout ());
01412 
01413       request.operation (tmp._retn (),
01414                          0,
01415                          1 /* TAO_ServerRequest owns string */);
01416     }
01417 
01418   return hdr_status ? 0 : -1;
01419 }
01420 
01421 int
01422 TAO_GIOP_Message_Lite::parse_locate_header (
01423     TAO_GIOP_Locate_Request_Header &request
01424   )
01425 {
01426   // Get the stream.
01427   TAO_InputCDR &msg = request.incoming_stream ();
01428 
01429   CORBA::Boolean hdr_status = 1;
01430 
01431   // Get the request id.
01432   CORBA::ULong req_id = 0;
01433   hdr_status = msg.read_ulong (req_id);
01434 
01435   // Store it in the Locate request classes.
01436   request.request_id (req_id);
01437 
01438   TAO::ObjectKey &object_key =
01439     request.object_key ();
01440 
01441   // Note that here there are no unions and so no problems.
01442   hdr_status = hdr_status && (msg >> object_key);
01443 
01444   return hdr_status ? 0 : -1;
01445 }
01446 
01447 int
01448 TAO_GIOP_Message_Lite::send_reply_exception (
01449     TAO_Transport *transport,
01450     TAO_ORB_Core* orb_core,
01451     CORBA::ULong request_id,
01452     IOP::ServiceContextList *svc_info,
01453     CORBA::Exception *x
01454   )
01455 {
01456   // Create a new output CDR stream
01457   char repbuf[ACE_CDR::DEFAULT_BUFSIZE];
01458 
01459 #if defined(ACE_INITIALIZE_MEMORY_BEFORE_USE)
01460   (void) ACE_OS::memset (repbuf,
01461                          '\0',
01462                          sizeof repbuf);
01463 #endif /* ACE_INITIALIZE_MEMORY_BEFORE_USE */
01464   TAO_OutputCDR output (repbuf,
01465                         sizeof repbuf,
01466                         TAO_ENCAP_BYTE_ORDER,
01467                         orb_core->output_cdr_buffer_allocator (),
01468                         orb_core->output_cdr_dblock_allocator (),
01469                         orb_core->output_cdr_msgblock_allocator (),
01470                         orb_core->orb_params ()->cdr_memcpy_tradeoff (),
01471                         TAO_DEF_GIOP_MAJOR,
01472                         TAO_DEF_GIOP_MINOR);
01473 
01474   transport->assign_translators(0,&output);
01475 
01476   // Make the GIOP & reply header. They are version specific.
01477   TAO_Pluggable_Reply_Params reply_params (transport);
01478   reply_params.request_id_ = request_id;
01479   reply_params.svc_ctx_.length (0);
01480 
01481   // Send back the service context we received.  (RTCORBA relies on
01482   // this).
01483   reply_params.service_context_notowned (svc_info);
01484 
01485   // A new try/catch block, but if something goes wrong now we have no
01486   // hope, just abort.
01487   ACE_DECLARE_NEW_CORBA_ENV;
01488 
01489   ACE_TRY
01490     {
01491       // Write the exception.
01492       reply_params.reply_status_ = TAO_GIOP_USER_EXCEPTION;
01493 
01494       if (CORBA::SystemException::_downcast (x) != 0)
01495         {
01496           reply_params.reply_status_ = TAO_GIOP_SYSTEM_EXCEPTION;
01497         }
01498 
01499       // Make the GIOP & reply header. They are version specific.
01500       this->write_reply_header (output,
01501                                 reply_params);
01502 
01503 
01504       x->_tao_encode (output ACE_ENV_ARG_PARAMETER);
01505       ACE_TRY_CHECK;
01506     }
01507   ACE_CATCH (CORBA::Exception, ex)
01508     {
01509       // Now we know that while handling the error an other error
01510       // happened -> no hope, close connection.
01511 
01512       // Close the handle.
01513       ACE_DEBUG ((LM_DEBUG,
01514                   ACE_TEXT ("(%P|%t|%N|%l) cannot marshal exception on transport %u: %p\n"),
01515                   transport->id (),
01516                   ACE_TEXT ("send_reply_exception ()")));
01517       return -1;
01518     }
01519   ACE_ENDTRY;
01520 
01521   return transport->send_message (output);
01522 }
01523 
01524 
01525 int
01526 TAO_GIOP_Message_Lite::write_locate_reply_mesg (
01527     TAO_OutputCDR & output,
01528     CORBA::ULong request_id,
01529     TAO_GIOP_Locate_Status_Msg &status_info
01530   )
01531 {
01532   // Note here we are making the Locate reply header which is *QUITE*
01533   // different from the reply header made by the make_reply () call..
01534 
01535   // Make the GIOP message header
01536   this->write_protocol_header (TAO_GIOP_LOCATEREPLY,
01537                                output);
01538 
01539   // Make the header for the locate request
01540   output.write_ulong (request_id);
01541   output.write_ulong (status_info.status);
01542 
01543   if (status_info.status == TAO_GIOP_OBJECT_FORWARD)
01544     {
01545       CORBA::Object_ptr object_ptr = status_info.forward_location_var.in ();
01546 
01547       if ((output << object_ptr) == 0)
01548         {
01549           if (TAO_debug_level > 0)
01550             ACE_DEBUG ((LM_DEBUG,
01551                         ACE_TEXT ("TAO (%P|%t|%N|%l) make_locate_reply-")
01552                         ACE_TEXT ("cannot marshal object reference\n")));
01553         }
01554     }
01555 
01556   return 1;
01557 }
01558 
01559 // Send an "I can't understand you" message -- again, the message is
01560 // prefabricated for simplicity.  This implies abortive disconnect (at
01561 // the application level, if not at the level of TCP).
01562 //
01563 // NOTE that IIOPLite will still benefit from TCP's orderly disconnect.
01564 int
01565 TAO_GIOP_Message_Lite::send_error (TAO_Transport *transport)
01566 {
01567   const char error_message [TAO_GIOP_LITE_HEADER_LEN] =
01568   {
01569     // The following works on non-ASCII platforms, such as MVS (which
01570     // uses EBCDIC).
01571     TAO_GIOP_MESSAGERROR,
01572     0, 0, 0, 0
01573   };
01574 
01575   this->dump_msg ("send_error",
01576                   (const u_char *) error_message,
01577                   TAO_GIOP_LITE_HEADER_LEN);
01578 
01579   ACE_Data_Block data_block (TAO_GIOP_LITE_HEADER_LEN,
01580                              ACE_Message_Block::MB_DATA,
01581                              error_message,
01582                              0,
01583                              0,
01584                              ACE_Message_Block::DONT_DELETE,
01585                              0);
01586   ACE_Message_Block message_block(&data_block);
01587   message_block.wr_ptr (TAO_GIOP_LITE_HEADER_LEN);
01588 
01589   size_t bt;
01590   int result = transport->send_message_block_chain (&message_block,
01591                                                     bt);
01592   if (result == -1)
01593     {
01594       if (TAO_debug_level > 0)
01595         {
01596           ACE_DEBUG ((
01597               LM_DEBUG,
01598               ACE_TEXT ("TAO (%N|%l|%P|%t) error sending error to transport %u, errno = %d\n"),
01599               transport->id (), errno
01600             ));
01601         }
01602     }
01603 
01604   return result;
01605 }
01606 
01607 void
01608 TAO_GIOP_Message_Lite::dump_msg (const char *label,
01609                                  const u_char *ptr,
01610                                  size_t len)
01611 {
01612   if (TAO_debug_level >= 5)
01613     {
01614       static const char *names [] =
01615       {
01616         "Request",
01617         "Reply",
01618         "CancelRequest",
01619         "LocateRequest",
01620         "LocateReply",
01621         "CloseConnection",
01622         "MessageError",
01623         "Fragment"
01624       };
01625 
01626       // Message name.
01627       const char *message_name = "UNKNOWN MESSAGE";
01628       u_long slot = ptr[TAO_GIOP_LITE_MESSAGE_TYPE_OFFSET];
01629 
01630       if (slot < sizeof (names)/sizeof(names[0]))
01631         {
01632           message_name = names [slot];
01633         }
01634 
01635       // Byte order.
01636       int byte_order = TAO_ENCAP_BYTE_ORDER;
01637 
01638       // request/reply id.
01639       CORBA::ULong tmp = 0;
01640       CORBA::ULong *id = &tmp;
01641 
01642       if (ptr[TAO_GIOP_LITE_MESSAGE_TYPE_OFFSET] == TAO_GIOP_REQUEST ||
01643           ptr[TAO_GIOP_LITE_MESSAGE_TYPE_OFFSET] == TAO_GIOP_REPLY)
01644         {
01645           // We are not sure where the read pointer is pointing
01646           // to. So, try to align teh pointer to a 4 byte boundary.
01647           char *buf = ACE_ptr_align_binary (ptr + TAO_GIOP_LITE_HEADER_LEN, 4);
01648 
01649           id = reinterpret_cast <CORBA::ULong *> (buf);
01650         }
01651 
01652       // Print.
01653       ACE_DEBUG ((LM_DEBUG,
01654                   ACE_TEXT ("(%P | %t):%s GIOP lite msg, ")
01655                   ACE_TEXT ("%d data bytes, %s endian, <%s = %d> \n"),
01656                   ACE_TEXT_CHAR_TO_TCHAR(label),
01657                   len - TAO_GIOP_LITE_HEADER_LEN,
01658                   (byte_order == TAO_ENCAP_BYTE_ORDER) ? ACE_TEXT("my") : ACE_TEXT("other"),
01659                   ACE_TEXT_CHAR_TO_TCHAR (message_name),
01660                   *id));
01661 
01662       if (TAO_debug_level >= 10)
01663         ACE_HEX_DUMP ((LM_DEBUG,
01664                        (const char *) ptr,
01665                        len,
01666                        ACE_TEXT ("GIOP lite message")));
01667     }
01668 }
01669 
01670 TAO_Queued_Data *
01671 TAO_GIOP_Message_Lite::make_queued_data (size_t sz)
01672 {
01673   // Get a node for the queue..
01674   TAO_Queued_Data *qd =
01675     TAO_Queued_Data::make_queued_data ();
01676 
01677   if (qd == 0)
01678     {
01679       return 0;
01680     }
01681 
01682   // Make a datablock for the size requested + something. The
01683   // "something" is required because we are going to align the data
01684   // block in the message block. During alignment we could loose some
01685   // bytes. As we may not know how many bytes will be lost, we will
01686   // allocate ACE_CDR::MAX_ALIGNMENT extra.
01687   ACE_Data_Block *db =
01688     this->orb_core_->create_input_cdr_data_block (sz +
01689                                                   ACE_CDR::MAX_ALIGNMENT);
01690 
01691   if (db == 0)
01692     {
01693       TAO_Queued_Data::release (qd);
01694       return 0;
01695     }
01696 
01697   ACE_Allocator *alloc =
01698     this->orb_core_->input_cdr_msgblock_allocator ();
01699 
01700   ACE_Message_Block mb (db,
01701                         0,
01702                         alloc);
01703 
01704   ACE_Message_Block *new_mb = mb.duplicate ();
01705 
01706   if (new_mb == 0)
01707     {
01708       TAO_Queued_Data::release (qd);
01709       db->release();
01710 
01711       return 0;
01712     }
01713 
01714   ACE_CDR::mb_align (new_mb);
01715 
01716   qd->msg_block_ = new_mb;
01717 
01718   return qd;
01719 }
01720 
01721 int
01722 TAO_GIOP_Message_Lite::generate_locate_reply_header (
01723     TAO_OutputCDR & /*cdr*/,
01724     TAO_Pluggable_Reply_Params_Base & /*params*/)
01725 {
01726   return 0;
01727 }
01728 
01729 
01730 int
01731 TAO_GIOP_Message_Lite::is_ready_for_bidirectional (TAO_OutputCDR & )
01732 {
01733   // No we dont support..
01734   return 0;
01735 }
01736 
01737 size_t
01738 TAO_GIOP_Message_Lite::header_length (void) const
01739 {
01740   return TAO_GIOP_LITE_HEADER_LEN;
01741 }
01742 
01743 size_t
01744 TAO_GIOP_Message_Lite::fragment_header_length (CORBA::Octet,
01745                                                CORBA::Octet) const
01746 {
01747   return 0;
01748 }
01749 
01750 void
01751 TAO_GIOP_Message_Lite::init_queued_data (TAO_Queued_Data* qd) const
01752 {
01753   qd->byte_order_    = TAO_ENCAP_BYTE_ORDER;
01754   qd->major_version_ = TAO_DEF_GIOP_MAJOR;
01755   qd->minor_version_ = TAO_DEF_GIOP_MINOR;
01756   qd->msg_type_      = this->message_type ();
01757 }
01758 
01759 /* @return -1 error, 0 ok */
01760 int
01761 TAO_GIOP_Message_Lite::consolidate_fragmented_message (TAO_Queued_Data* /* qd */,
01762                                                        TAO_Queued_Data *& /* msg */)
01763 {
01764   if (TAO_debug_level > 3)
01765     {
01766       ACE_ERROR ((LM_ERROR,
01767                   ACE_TEXT ("(%P | %t):%s GIOP lite msg, ")
01768                   ACE_TEXT ("Error, fragmented messages not supported\n")));
01769     }
01770   return -1; // not implemented, not supported
01771 }
01772 
01773 
01774 
01775 /// Remove all fragments from stack corelating to CancelRequest @a qd.
01776 /// @return -1 on failure, 0 on success, 1 no fragment on stack
01777 /// relating to CancelRequest.
01778 int
01779 TAO_GIOP_Message_Lite::discard_fragmented_message (const TAO_Queued_Data *)
01780 {
01781   return 1; // no fragment on stack relating to cancel-request
01782 }
01783 
01784 TAO_GIOP_Fragmentation_Strategy *
01785 TAO_GIOP_Message_Lite::fragmentation_strategy (void)
01786 {
01787   return 0; // Fragmentation is unsupported in GIOP lite.
01788 }
01789 
01790 
01791 TAO_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 11:54:12 2006 for TAO by doxygen 1.3.6