Merge branch 'master' into jwi-bcc64xsingletonwarning
[ACE_TAO.git] / ACE / ASNMP / asnmp / pdu.cpp
blobd80c4fa4c26f9f4439bba545ad11ddd016459598
2 //=============================================================================
3 /**
4 * @file pdu.cpp
6 * Pdu class implementation. Encapsulation of an SMI Protocol
7 * Data Unit (PDU) in C++.
9 * @author Peter E MellquistMichael R MacFaden mrm@cisco.com - rework & ACE port
11 //=============================================================================
13 /*===================================================================
14 Copyright (c) 1996
15 Hewlett-Packard Company
17 ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
18 Permission to use, copy, modify, distribute and/or sell this software
19 and/or its documentation is hereby granted without fee. User agrees
20 to display the above copyright notice and this license notice in all
21 copies of the software and any documentation of the software. User
22 agrees to assume all liability for the use of the software; Hewlett-Packard
23 makes no representations about the suitability of this software for any
24 purpose. It is provided "AS-IS without warranty of any kind,either express
25 or implied. User hereby grants a royalty-free license to any and all
26 derivatives based upon this software code base.
27 =====================================================================*/
29 #include "asnmp/snmp.h"
30 #include "asnmp/pdu.h" // include Pdu class definition
31 #include "ace/OS_NS_string.h"
32 #include "ace/OS_NS_stdio.h"
34 //=====================[ constructor no args ]=========================
35 Pdu::Pdu(): vb_count_(0), error_status_(0), error_index_(0),
36 validity_(0), request_id_(0), pdu_type_(0), notify_timestamp_(0),
37 output_(0)
41 //=====================[ constructor with vbs_ and count ]==============
42 Pdu::Pdu( Vb* pvbs, const int pvb_count): vb_count_(0), error_index_(0),
43 validity_(0), request_id_(0), pdu_type_(0), notify_timestamp_(0),
44 output_(0)
46 int z = 0; // looping variable
48 // zero is ok
49 if ( pvb_count == 0) {
50 validity_ = 1;
51 return;
54 // check for over then max
55 if ( pvb_count > MAX_VBS) {
56 validity_ = 0;
57 return;
60 // loop through and assign internal vbs_
61 for (z = 0;z < pvb_count; z++) {
62 validity_ = 0;
63 ACE_NEW(vbs_[z], Vb( pvbs[z]));
64 validity_ = 1;
67 // assign the vb count
68 vb_count_ = pvb_count;
70 validity_ = 1;
73 //=====================[ constructor with another Pdu instance ]========
74 Pdu::Pdu( const Pdu &pdu): vb_count_(0),
75 error_index_(0), validity_(0), request_id_(0), pdu_type_(0),
76 notify_timestamp_(0), output_(0)
78 *this = pdu;
79 return;
82 //=====================[ destructor ]====================================
83 Pdu::~Pdu()
85 delete_all_vbs();
86 delete [] output_;
90 //=====================[ assignment to another Pdu object overloaded ]===
91 Pdu& Pdu::operator=( const Pdu &pdu)
93 if (this == &pdu)
94 return *this;
96 int z; // looping variable
98 // Initialize all mv's
99 error_status_ = pdu.error_status_;
100 error_index_ = pdu.error_index_;
101 request_id_ = pdu.request_id_;
102 pdu_type_ = pdu.pdu_type_;
103 notify_id_ = pdu.notify_id_;
104 notify_timestamp_ = pdu.notify_timestamp_;
105 notify_enterprise_ = pdu.notify_enterprise_;
106 validity_ = 1;
108 // free up old vbs_
109 for ( z = 0;z < vb_count_; z++)
110 delete vbs_[z];
111 vb_count_ = 0;
113 // check for zero case
114 if ( pdu.vb_count_ == 0) {
115 return *this;
118 // loop through and fill em up
119 for (z = 0; z < pdu.vb_count_; z++) {
120 validity_ = 0;
121 ACE_NEW_RETURN(vbs_[z], Vb ( *(pdu.vbs_[z])), *this);
122 validity_ = 1;
125 vb_count_ = pdu.vb_count_;
126 return *this;
129 // append operator, appends a string
130 Pdu& Pdu::operator+=( Vb &vb)
132 // do we have room?
133 if ( vb_count_ + 1 > MAX_VBS)
134 return *this;
136 // add the new one
137 validity_ = 0;
138 ACE_NEW_RETURN(vbs_[vb_count_], Vb (vb), *this);
139 // set up validity_
140 validity_ = 1;
142 // up the vb count
143 vb_count_++;
145 // return self reference
146 return *this;
149 // return fomatted version of this object
150 const char * Pdu::to_string()
152 // determine how big a buffer and allocate it
153 const int HEADER_STR = 100;
154 unsigned size = HEADER_STR; // header takes up this much room
155 int z;
157 for ( z = 0; z < vb_count_; z++)
158 size += ACE_OS::strlen(vbs_[z]->to_string());
160 ACE_NEW_RETURN(output_, char[size], "");
162 // print pdu header info
163 ACE_OS::sprintf(output_, "pdu: valid: %d type:%d, req:%d, cnt: %d, err stat: %d \
164 err idx: %d\n", validity_, pdu_type_, (int) request_id_,
165 vb_count_, error_status_, error_index_ );
167 // now append vb pairs in this object
168 for ( z = 0; z < vb_count_; z++) {
169 ACE_OS::strcat(output_, vbs_[z]->to_string());
170 ACE_OS::strcat(output_, "\n\t");
173 return output_;
177 //=====================[ extract Vbs from Pdu ]==========================
178 // how do you know that the caler has enough memory???
179 // should I self allocate this in here and require the
180 // caller then to free it up at soem later time
181 int Pdu::get_vblist( Vb* pvbs, const int pvb_count)
183 if ((!pvbs) || ( pvb_count < 0) || ( pvb_count > vb_count_))
184 return 0;
186 // loop through all vbs_ and assign to params
187 int z;
188 for (z = 0; z < pvb_count; z++)
189 pvbs[z] = *vbs_[z];
191 return 1;
194 //=====================[ deposit Vbs ]===================================
195 int Pdu::set_vblist( Vb* pvbs, const int pvb_count)
197 // if invalid then don't destroy
198 if ((!pvbs) || ( pvb_count < 0) || ( pvb_count > MAX_VBS))
199 return 0;
201 // free up current vbs_
202 int z;
203 for ( z = 0; z < vb_count_; z++)
204 delete vbs_[z];
205 vb_count_ = 0;
207 // check for zero case
208 if ( pvb_count == 0) {
209 validity_ = 1;
210 error_status_ = 0;
211 error_index_ = 0;
212 request_id_ = 0;
213 return 0;
217 // loop through all vbs_ and reassign them
218 for ( z = 0; z < pvb_count; z++) {
219 validity_ = 0;
220 ACE_NEW_RETURN(vbs_[z], Vb (pvbs[z]), 0);
221 validity_ = 1;
224 vb_count_ = pvb_count;
226 // clear error status and index since no longer valid
227 // request id may still apply so don't reassign it
228 error_status_ = 0;
229 error_index_ = 0;
230 validity_ = 1;
232 return 1;
235 //===================[ get a particular vb ]=============================
236 // here the caller has already instantiated a vb object
237 // index is zero based
238 int Pdu::get_vb( Vb &vb, const int index) const
240 // can't have an index less than 0
241 if ( index < 0)
242 return 0;
244 // can't ask for something not there
245 if ( index > (vb_count_ - 1))
246 return 0;
248 // asssign it
249 vb = *vbs_[index];
251 return 1;
254 //===================[ set a particular vb ]=============================
255 int Pdu::set_vb( Vb &vb, const int index)
257 // can't set a vb at index less than 0
258 if ( index < 0)
259 return 0;
261 // can't ask for something not there
262 if ( index > (vb_count_ - 1))
263 return 0;
265 // delete what is there
266 delete vbs_[index];
268 // assign it
269 validity_ = 0;
270 ACE_NEW_RETURN(vbs_[index], Vb (vb), 0);
271 validity_ = 1;
273 return 1;
276 //=====================[ return number of vbs_ ]==========================
277 int Pdu::get_vb_count() const
279 return vb_count_;
282 //=====================[ return the error status ]=======================
283 int Pdu::get_error_status() const
285 return error_status_;
288 const char *Pdu::agent_error_reason()
290 int pdu_err = get_error_status();
291 if (pdu_err == 0) // any real error?
292 return "not in error state";
294 int n_vbs = get_vb_count();
295 Vb bad;
296 get_vb(bad, get_error_index() -1); // not zero based??
297 const char *pmsg = Snmp::error_string(get_error_status());
298 const char *id = bad.to_string_oid();
299 const char *val = bad.to_string_value();
300 const int HDR_SZ = 100;
302 if (!output_) {
303 int size = ACE_OS::strlen(pmsg) + ACE_OS::strlen(id) +
304 ACE_OS::strlen(val);
305 ACE_NEW_RETURN(output_, char[size + HDR_SZ], "");
308 ACE_OS::sprintf(output_,
309 "FAIL PDU REPORT: pdu id: %lu vb cnt: %d vb idx: %d\n"
310 " msg: %s vb oid: %s value: %s\n",
311 get_request_id(), n_vbs, get_error_index(),
312 pmsg, id, val);
314 return output_;
317 //=====================[ set the error status ]==========================
318 // friend
319 void set_error_status( Pdu *pdu, const int status)
321 if (pdu)
322 pdu->error_status_ = status;
325 //=====================[ return the error index ]========================
326 int Pdu::get_error_index() const
328 return error_index_;
331 //=====================[ set the error index ]===========================
332 // friend
333 void set_error_index( Pdu *pdu, const int index)
335 if (pdu)
336 pdu->error_index_ = index;
339 //=====================[ clear error status ]=============================
340 void clear_error_status( Pdu *pdu)
342 if (pdu)
343 pdu->error_status_ = 0;
346 //=====================[ clear error index ]==============================
347 void clear_error_index( Pdu *pdu)
349 if (pdu)
350 pdu->error_index_ = 0;
353 //=====================[ return the request id ]==========================
354 unsigned long Pdu::get_request_id() const
356 return request_id_;
359 //=====================[ set the request id ]=============================
360 // friend function
361 void set_request_id( Pdu *pdu, const unsigned long rid)
363 if (pdu)
364 pdu->request_id_ = rid;
367 //=====================[ returns validity_ of Pdu instance ]===============
368 int Pdu::valid() const
370 return validity_;
373 //=====================[ get the pdu type ]===============================
374 unsigned short Pdu::get_type()const
376 return pdu_type_;
379 // set the pdu type
380 void Pdu::set_type( unsigned short type)
382 pdu_type_ = type;
386 // trim off the last vb
387 int Pdu::trim(const int p)
389 int lp = p;
391 // verify that lp is legal
392 if ( lp < 0 || lp > vb_count_)
393 return 0;
395 while ( lp != 0) {
396 if ( vb_count_ > 0) {
397 delete vbs_[vb_count_ - 1];
398 vb_count_--;
400 lp--;
402 return 1;
406 // delete a Vb anywhere within the Pdu
407 int Pdu::delete_vb( const int p)
409 // position has to be in range
410 if (( p < 0) || ( p > (vb_count_ - 1)))
411 return 0;
413 // safe to remove it
414 delete vbs_[ p];
416 for ( int z=p;z < (vb_count_-1);z++) {
417 vbs_[z] = vbs_[z+1];
419 vb_count_--;
421 return 1;
424 void Pdu::delete_all_vbs()
426 for ( int z = 0; z < vb_count_; z++)
427 delete vbs_[z];
428 vb_count_ = 0;
432 // set notify timestamp
433 void Pdu::set_notify_timestamp( const TimeTicks & timestamp)
435 notify_timestamp_ = timestamp;
439 // get notify timestamp
440 void Pdu::get_notify_timestamp( TimeTicks & timestamp) const
442 timestamp = notify_timestamp_;
445 // set the notify id
446 void Pdu::set_notify_id( const Oid id)
448 notify_id_ = id;
451 // get the notify id
452 void Pdu::get_notify_id( Oid &id) const
454 id = notify_id_;
457 // set the notify enterprise
458 void Pdu::set_notify_enterprise( const Oid &enterprise)
460 notify_enterprise_ = enterprise;
463 // get the notify enterprise
464 void Pdu::get_notify_enterprise( Oid & enterprise) const
466 enterprise = notify_enterprise_;
469 // ------ class VbIter -------------------
470 VbIter::VbIter(Pdu& pdu): idx_(-1), pdu_(&pdu)
474 // returns 1 if ok, else 0 if none left
475 int VbIter::next(Vb& vb)
477 if (idx_ == -1) {
478 idx_ = 0;
479 pdu_->get_vb(vb, idx_++);
480 return 1;
482 else
483 if (idx_ < pdu_->get_vb_count()) {
484 pdu_->get_vb(vb, idx_++);
485 return 1;
487 return 0; // non left