void TAO_ECG_CDR_Message_Sender::send_message (const TAO_OutputCDR &cdr, const ACE_INET_Addr &addr) { if (this->endpoint_rptr_.get () == 0) { ORBSVCS_ERROR ((LM_ERROR, "Attempt to invoke send_message() " "on non-initialized sender object.\n")); throw CORBA::INTERNAL (); } CORBA::ULong max_fragment_payload = this->mtu () - TAO_ECG_CDR_Message_Sender::ECG_HEADER_SIZE; // ACE_ASSERT (max_fragment_payload != 0); #if defined (ACE_HAS_BROKEN_DGRAM_SENDV) const int TAO_WRITEV_MAX = ACE_IOV_MAX - 1; #else const int TAO_WRITEV_MAX = ACE_IOV_MAX; #endif /* ACE_HAS_BROKEN_DGRAM_SENDV */ iovec iov[TAO_WRITEV_MAX]; CORBA::ULong total_length; CORBA::ULong fragment_count = this->compute_fragment_count (cdr.begin (), cdr.end (), TAO_WRITEV_MAX, max_fragment_payload, total_length); CORBA::ULong request_id = this->endpoint_rptr_->next_request_id (); // Reserve the first iovec for the header... int iovcnt = 1; CORBA::ULong fragment_id = 0; CORBA::ULong fragment_offset = 0; CORBA::ULong fragment_size = 0; for (const ACE_Message_Block* b = cdr.begin (); b != cdr.end (); b = b->cont ()) { CORBA::ULong l = b->length (); char* rd_ptr = b->rd_ptr (); iov[iovcnt].iov_base = rd_ptr; iov[iovcnt].iov_len = l; fragment_size += l; ++iovcnt; while (fragment_size > max_fragment_payload) { // This fragment is full, we have to send it... // First adjust the last iov entry: CORBA::ULong last_mb_length = max_fragment_payload - (fragment_size - l); iov[iovcnt - 1].iov_len = last_mb_length; this->send_fragment (addr, request_id, total_length, max_fragment_payload, fragment_offset, fragment_id, fragment_count, iov, iovcnt); ++fragment_id; fragment_offset += max_fragment_payload; // Reset, but don't forget that the last Message_Block // may need to be sent in multiple fragments.. l -= last_mb_length; rd_ptr += last_mb_length; iov[1].iov_base = rd_ptr; iov[1].iov_len = l; fragment_size = l; iovcnt = 2; } if (fragment_size == max_fragment_payload) { // We filled a fragment, but this time it was filled // exactly, the treatment is a little different from the // loop above... this->send_fragment (addr, request_id, total_length, max_fragment_payload, fragment_offset, fragment_id, fragment_count, iov, iovcnt); ++fragment_id; fragment_offset += max_fragment_payload; iovcnt = 1; fragment_size = 0; } if (iovcnt == TAO_WRITEV_MAX) { // Now we ran out of space in the iovec, we must send a // fragment to work around that.... this->send_fragment (addr, request_id, total_length, fragment_size, fragment_offset, fragment_id, fragment_count, iov, iovcnt); ++fragment_id; fragment_offset += fragment_size; iovcnt = 1; fragment_size = 0; } } // There is something left in the iovvec that we must send // also... if (iovcnt != 1) { // Now we ran out of space in the iovec, we must send a // fragment to work around that.... this->send_fragment (addr, request_id, total_length, fragment_size, fragment_offset, fragment_id, fragment_count, iov, iovcnt); ++fragment_id; fragment_offset += fragment_size; // reset, not needed here... // iovcnt = 1; // fragment_size = 0; } // ACE_ASSERT (total_length == fragment_offset); // ACE_ASSERT (fragment_id == fragment_count); }
int ACE_TMAIN (int, ACE_TCHAR *[]) { int status = 0; for (CORBA::ULong i = 16; i != 64; ++i) { ACE_Message_Block mb (i + ACE_CDR::MAX_ALIGNMENT); ACE_CDR::mb_align (&mb); mb.wr_ptr (i); CORBA::Double dbl = i; TAO_OutputCDR cdr; cdr.write_ulong (i); // length cdr.write_octet_array_mb (&mb); cdr.write_double (dbl); cdr.write_double (dbl); TAO_InputCDR input (cdr); CORBA::ULong len; input.read_ulong (len); if (len != i) { ACE_DEBUG ((LM_DEBUG, "ERROR: mismatched lengths," " got %d, expected %d\n", len, i)); } ACE_Message_Block read_mb (len + ACE_CDR::MAX_ALIGNMENT); ACE_CDR::mb_align (&mb); mb.wr_ptr (len); input.read_char_array (mb.rd_ptr (), len); CORBA::Double read_dbl; if (input.read_double (read_dbl) == 0) ACE_DEBUG ((LM_DEBUG, "Failure reading double...\n")); if (!ACE::is_equal (read_dbl, dbl)) { status = 1; ACE_DEBUG ((LM_DEBUG, "ERROR: mismatched doubles," " got %f, expected %f\n", read_dbl, dbl)); for (const ACE_Message_Block *j = cdr.begin (); j != cdr.end (); j = j->cont ()) { ACE_HEX_DUMP ((LM_DEBUG, j->rd_ptr (), j->length (), ACE_TEXT("Output CDR stream"))); } TAO_InputCDR debug (cdr); ACE_HEX_DUMP ((LM_DEBUG, debug.rd_ptr (), debug.length (), ACE_TEXT("Input CDR stream"))); } } return status; }