#include "GIOP_Buffer.h" #include "ace/OS_NS_string.h" #include "ace/Log_Msg.h" static const char *size_leadin_1_5 = "GIOP v1."; //"x msg, "; static size_t leadin_len_1_5 = 15; static const char *size_leadin_1_6 = "GIOP message v1."; //2, "; static size_t leadin_len_1_6 = 19; const char *GIOP_Buffer::size_leadin = 0; size_t GIOP_Buffer::leadin_len = 0; const size_t GIOP_Buffer::giop_header_len = 12; void GIOP_Buffer::init_leadin (int version) { if (size_leadin == 0) { if (version == 150) { size_leadin = size_leadin_1_5; leadin_len = leadin_len_1_5; } else { size_leadin = size_leadin_1_6; leadin_len = leadin_len_1_6; } } } // GIOP 1.2 header: 12 bytes // Magic: 4 // ver: 2 // flags: 1 // bo // type: 1 // req/repl/lf/excp // len: 4 // // Request 1.2 header: // req_id: 4 // flags: 1 // RESVD: 3 // Address disposition: 4 // target: <4 len, + len> [0-3 pad] // opname: <4 len, + len> // GIOP 1.0 header: 12 bytes // Magic: 4 // ver: 2 // byte_order: 1 // type: 1 // req/repl/lf/excp // len: 4 // // Request 1.0 header: /* struct RequestHeader_1_0 { // Renamed from RequestHeader IOP::ServiceContextList service_context; unsigned long request_id; boolean response_expected; sequence object_key; string operation; CORBA::OctetSeq requesting_principal; }; */ // service_context: 4(count)+contexts. // context id: 4 // content blob: 4(len) + len octets + (0-3)pad // request_id: 4 // respexp: 1 // RESVD: 3 // Address disposition: 4 // target: <4 len, + len> [0-3 pad] // opname: <4 len, + len> /* struct ReplyHeader_1_0 { // Renamed from ReplyHeader IOP::ServiceContextList service_context; unsigned long request_id; ReplyStatusType_1_0 reply_status; }; // GIOP 1.1 typedef ReplyHeader_1_0 ReplyHeader_1_1; // Same Header contents for 1.0 and 1.1 #else // GIOP 1.2, 1.3 enum ReplyStatusType_1_2 { NO_EXCEPTION, USER_EXCEPTION, SYSTEM_EXCEPTION, LOCATION_FORWARD, LOCATION_FORWARD_PERM,// new value for 1.2 NEEDS_ADDRESSING_MODE // new value for 1.2 }; struct ReplyHeader_1_2 { unsigned long request_id; ReplyStatusType_1_2 reply_status; IOP::ServiceContextList service_context; }; */ //static const size_t target_offset_12 = GIOP_Buffer::giop_header_len + 12; // 12 = req_id + flags + RESVD + addr disp. GIOP_Buffer::GIOP_Buffer(void) : cdr_ (0), preamble_(), log_offset_(0), thr_(0), time_(), expected_req_id_(0), expected_size_(0), expected_type_(0), buffer_size_(0), wr_pos_ (0), octets_ (0), owner_ (0), buffer_lost_ (false), sending_(false), oid_ (0), oid_len_ (0), opname_ (0), req_id_ (0), resp_exp_ (0), reply_status_ (0), ver_minor_ (0), msg_size_ (0), num_contexts_ (0), header_parsed_ (false), payload_start_ (0), payload_size_ (0) { } GIOP_Buffer::GIOP_Buffer(const char *text, size_t offset, Thread *thread, Invocation *owner) : cdr_ (0), preamble_(text), log_offset_(offset), thr_(thread), time_(ACE_Time_Value::zero), expected_req_id_(0), expected_size_(0), expected_type_(0), buffer_size_(0), wr_pos_ (0), octets_ (0), owner_ (owner), buffer_lost_ (false), sending_(false), oid_ (0), oid_len_ (0), opname_ (0), req_id_ (0), resp_exp_ (0), reply_status_ (0), ver_minor_ (0), msg_size_ (0), num_contexts_ (0), header_parsed_ (false), payload_start_ (0), payload_size_ (0) { const char *size_str = ACE_OS::strstr(text, size_leadin); if (size_str != 0) { size_str += leadin_len; //ACE_OS::strlen (size_leadin); // size_str += 3; this->expected_size_ = ACE_OS::strtol(size_str, 0, 10); const char *id = ACE_OS::strchr(size_str, '[') + 1; this->expected_req_id_ = ACE_OS::strtol(id, 0, 10); } this->sending_ = ACE_OS::strstr(text,"send") ? 0 : 1; this->expected_type_ = ACE_OS::strstr(text,"Request") ? 0 : 1; } void GIOP_Buffer::owner (Invocation *owner) { this->owner_ = owner; } Invocation * GIOP_Buffer::owner (void) { return this->owner_; } void GIOP_Buffer::init_buf (const char *text, size_t offset) { // GIOP message - HEXDUMP this->log_offset_ = offset; const char * size_str = ACE_OS::strstr (text,"HEXDUMP ") + 8; this->buffer_size_ = ACE_OS::strtol (size_str, 0, 10); this->payload_size_ = this->buffer_size_ - 12; size_str = ACE_OS::strstr (text,"showing first "); if (size_str != 0) { size_str += 14; this->buffer_size_ = ACE_OS::strtol (size_str, 0, 10); } if (this->octets_ != 0) { delete [] this->octets_; } this->octets_ = new char [this->buffer_size_]; ACE_OS::memset (this->octets_, 0, this->buffer_size_); this->wr_pos_ = this->octets_; } GIOP_Buffer::~GIOP_Buffer(void) { delete [] this->octets_; } int GIOP_Buffer::add_octets (const char *text, size_t offset) { if (this->octets_ == 0) { this->init_buf(text, offset); return 0; } const char *c = text; char *err; for (int count = 0; count < 16 && this->cur_size() < this->buffer_size_; count++) { if (count == 8) ++c; int o = ::strtol(c, &err, 16); if (err == c || *err == 0) return -1; *this->wr_pos_++ = o; c = err+1; } size_t cs = this->cur_size(); int rtn = 0; if (!this->header_parsed_) { this->header_parsed_ = this->parse_header(); if (this->header_parsed_ ) rtn = 1; } if (cs == this->buffer_size_) { char vmaj = this->octets_[4]; char order = this->octets_[6]; delete this->cdr_; this->cdr_ = new ACE_InputCDR (this->octets_, this->cur_size(), order, vmaj, this->ver_minor_); this->cdr_->skip_bytes (this->payload_start_ - this->octets_); rtn = -1; } return rtn; } bool GIOP_Buffer::sending (void) const { return this->sending_; } bool GIOP_Buffer::is_full (void) const { return this->buffer_size_ > 0 && this->cur_size() == this->buffer_size_; } char GIOP_Buffer::type (void) const { if (this->octets_ == 0) return 127; return this->octets_[7]; } char GIOP_Buffer::expected_type (void) const { return this->expected_type_; } char GIOP_Buffer::minor_version (void) const { return this->ver_minor_; } size_t GIOP_Buffer::reply_status (void) const { return this->reply_status_; } size_t GIOP_Buffer::num_contexts (void) const { return this->num_contexts_; } bool GIOP_Buffer::is_oneway (void) { if (this->octets_ == 0) { return false; } if (!this->header_parsed_) this->header_parsed_ = this->parse_header(); return (resp_exp_ &1) == 0; } size_t GIOP_Buffer::log_posn (void) const { return this->log_offset_; } Thread * GIOP_Buffer::thread (void) { return this->thr_; } const ACE_Time_Value & GIOP_Buffer::time (void) const { return this->time_; } void GIOP_Buffer::time (const ACE_Time_Value &t) { this->time_ = t; } const ACE_CString & GIOP_Buffer::preamble (void) const { return this->preamble_; } size_t GIOP_Buffer::expected_size (void) const { return this->expected_size_; } size_t GIOP_Buffer::msg_size (void) { if (this->cur_size() < 12) return 0; if (!this->header_parsed_) this->header_parsed_ = this->parse_header(); return (size_leadin == size_leadin_1_5) ? this->payload_size_ : this->msg_size_; } size_t GIOP_Buffer::expected_req_id (void) const { return this->expected_req_id_; } size_t GIOP_Buffer::actual_req_id (void) { if (this->octets_ == 0) return 0; if (!this->header_parsed_) this->header_parsed_ = this->parse_header(); return this->req_id_; } size_t GIOP_Buffer::cur_size (void) const { return this->wr_pos_ - this->octets_; } bool GIOP_Buffer::parse_svc_contexts (void) { ACE_CDR::ULong temp; ACE_CDR::ULong num_svc_cont; if ( !(*this->cdr_ >> num_svc_cont)) return false; this->num_contexts_ = static_cast(num_svc_cont); while (num_svc_cont > 0) { if (!(*this->cdr_ >> temp)) // tag really return false; if (!(*this->cdr_ >> temp)) return false; if ((this->cur_size() == this->buffer_size_) && (this->cdr_->length() < temp)) { return this->cdr_->skip_bytes (this->cdr_->length()); } if (!this->cdr_->skip_bytes(temp)) { return this->cur_size() == this->buffer_size_; } --num_svc_cont; } return true; } bool GIOP_Buffer::parse_header (void) { if (this->octets_ == 0 || this->cur_size() < 12) { return false; } char vmaj = this->octets_[4]; this->ver_minor_ = this->octets_[5]; char order = this->octets_[6]; char mtype = this->octets_[7]; if (mtype > 1) // not a request or reply { return false; } delete this->cdr_; this->cdr_ = new ACE_InputCDR (this->octets_, this->cur_size(), order, vmaj, this->ver_minor_); this->cdr_->skip_bytes (8); this->payload_start_ = this->cdr_->rd_ptr(); ACE_CDR::ULong len_ulong; if (!(*this->cdr_ >> len_ulong)) return false; this->msg_size_ = len_ulong; if (this->ver_minor_ < 2) { if (!this->parse_svc_contexts()) { return false; } } if (!(*this->cdr_ >> len_ulong)) { return false; } this->req_id_ = static_cast(len_ulong); switch (mtype) { case 0: //Request if (!(*this->cdr_ >> this->resp_exp_)) { return false; } if (this->ver_minor_ > 1 && !(*this->cdr_ >> len_ulong)) // address disposition { return false; } if (!(*this->cdr_ >> len_ulong)) { return false; } this->oid_len_ = static_cast(len_ulong); this->oid_ = this->cdr_->rd_ptr(); if (!this->cdr_->skip_bytes(len_ulong)) { return false; } if (!(*this->cdr_ >> len_ulong)) { return false; } this->opname_ = this->cdr_->rd_ptr(); if (!this->cdr_->skip_bytes(len_ulong)) { return false; } break; case 1: //Reply if (!(*this->cdr_ >> len_ulong)) { return false; } this->reply_status_ = static_cast(len_ulong); break; default: return true; } if (this->ver_minor_ > 1) { if (!this->parse_svc_contexts()) return false; } this->cdr_->align_read_ptr (8); this->payload_start_ = this->cdr_->rd_ptr(); return true; } const char * GIOP_Buffer::target_oid (size_t &len) { if (this->octets_ == 0) { return 0; } if (!this->header_parsed_) this->header_parsed_ = this->parse_header(); if (this->oid_ == 0) return 0; len = this->oid_len_; return this->oid_; } const char * GIOP_Buffer::operation (void) { if (octets_ == 0) return 0; if (!this->header_parsed_) this->header_parsed_ = this->parse_header(); return this->opname_; } ACE_InputCDR & GIOP_Buffer::payload (void) { if (octets_ != 0 && !this->header_parsed_) this->header_parsed_ = this->parse_header(); return *this->cdr_; } bool GIOP_Buffer::has_octets (void) const { return (octets_ != 0); } bool GIOP_Buffer::validate (void) { return this->expected_req_id_ == this->actual_req_id() && this->expected_type_ == this->type() && this->expected_size_ == this->msg_size(); } bool GIOP_Buffer::matches (GIOP_Buffer *other) const { if (other->header_parsed_) { return this->expected_req_id_ == other->actual_req_id() && this->expected_type_ == other->type() && (this->expected_size_ == other->msg_size() || this->expected_size_ == other->msg_size() + 4); } return this->expected_req_id_ == other->expected_req_id() && this->expected_type_ == other->expected_type() && this->sending_ == other->sending() && this->expected_size_ == other->expected_size(); } void GIOP_Buffer::reset (void) { this->octets_ = 0; this->wr_pos_ = 0; this->buffer_size_ = 0; this->payload_size_ = 0; this->buffer_lost_ = true; this->header_parsed_ = false; this->opname_ = 0; } void GIOP_Buffer::transfer_from (GIOP_Buffer *other) { delete this->octets_; this->octets_ = other->octets_; this->wr_pos_ = other->wr_pos_; this->buffer_size_ = other->buffer_size_; this->payload_size_ = other->payload_size_; this->header_parsed_ = false; other->reset(); } void GIOP_Buffer::swap (GIOP_Buffer *other) { char *tmp_octets = this->octets_; char *tmp_wr_pos = this->wr_pos_; size_t tmp_bsize = this->buffer_size_; size_t tmp_psize = this->payload_size_; this->octets_ = other->octets_; this->wr_pos_ = other->wr_pos_; this->buffer_size_ = other->buffer_size_; this->payload_size_ = other->payload_size_; other->octets_ = tmp_octets; other->wr_pos_ = tmp_wr_pos; other->buffer_size_ = tmp_bsize; other->payload_size_= tmp_psize; }