Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <boost/bind.hpp>
00020
00021 #include "master_proxy.hpp"
00022 #include "OpenPDU.hpp"
00023 #include "ClosePDU.hpp"
00024 #include "ResponsePDU.hpp"
00025 #include "RegisterPDU.hpp"
00026 #include "GetPDU.hpp"
00027 #include "helper.hpp"
00028 #include "types.hpp"
00029
00030 #include <iostream>
00031 using namespace std;
00032
00033 using namespace agentxcpp;
00034 using namespace boost;
00035 using boost::shared_ptr;
00036
00037
00038
00039
00040
00041
00042 master_proxy::master_proxy(boost::asio::io_service* _io_service,
00043 std::string _description,
00044 byte_t _default_timeout,
00045 oid _id,
00046 std::string _filename) :
00047 io_service(_io_service),
00048 io_service_by_user(true),
00049 socket_file(_filename.c_str()),
00050 description(_description),
00051 default_timeout(_default_timeout),
00052 id(_id)
00053 {
00054
00055 byte_t timeout;
00056 timeout = (this->default_timeout == 0) ? 1 : this->default_timeout;
00057 connection = new connector(shared_ptr<boost::asio::io_service>(io_service),
00058 _filename.c_str(),
00059 timeout);
00060
00061
00062 this->connection->register_handler( this );
00063
00064
00065 try
00066 {
00067
00068 this->connect();
00069 }
00070 catch(disconnected)
00071 {
00072
00073 }
00074 }
00075
00076
00077
00078 master_proxy::master_proxy(std::string _description,
00079 byte_t _default_timeout,
00080 oid _id,
00081 std::string _filename) :
00082 io_service(new boost::asio::io_service()),
00083 io_service_by_user(false),
00084 socket_file(_filename.c_str()),
00085 description(_description),
00086 default_timeout(_default_timeout),
00087 id(_id)
00088 {
00089
00090 byte_t timeout;
00091 timeout = (this->default_timeout == 0) ? 1 : this->default_timeout;
00092 connection = new connector(shared_ptr<boost::asio::io_service>(io_service),
00093 _filename.c_str(),
00094 timeout);
00095
00096
00097 this->connection->register_handler( this );
00098
00099
00100 try
00101 {
00102
00103 this->connect();
00104 }
00105 catch(disconnected)
00106 {
00107
00108 }
00109 catch(...)
00110 {
00111
00112 }
00113 }
00114
00115
00116 void master_proxy::connect()
00117 {
00118 if( this->connection->is_connected() )
00119 {
00120
00121 return;
00122 }
00123
00124
00125 registrations.clear();
00126 variables.clear();
00127
00128
00129 try
00130 {
00131 this->connection->connect();
00132 }
00133 catch(boost::system::system_error)
00134 {
00135 throw;
00136 }
00137
00138 boost::shared_ptr<ResponsePDU> response;
00139
00140 try
00141 {
00142
00143 OpenPDU openpdu;
00144 openpdu.set_timeout(default_timeout);
00145 openpdu.set_id(id);
00146
00147 this->connection->send(openpdu);
00148
00149
00150
00151 response = this->connection->wait_for_response(openpdu.get_packetID());
00152 }
00153 catch(disconnected)
00154 {
00155 throw;
00156 }
00157 catch(timeout_error)
00158 {
00159 throw disconnected();
00160 }
00161
00162
00163 if(response->get_error() != ResponsePDU::noAgentXError)
00164 {
00165
00166 this->connection->disconnect();
00167 throw disconnected();
00168 }
00169
00170
00171 this->sessionID = response->get_sessionID();
00172 }
00173
00174
00175
00176
00177 void master_proxy::disconnect(ClosePDU::reason_t reason)
00178 {
00179 if( ! this->connection->is_connected() )
00180 {
00181
00182 return;
00183 }
00184
00185
00186
00187
00188
00189
00190 boost::shared_ptr<ResponsePDU> response;
00191
00192
00193 try
00194 {
00195
00196 std::list< boost::shared_ptr<RegisterPDU> >::const_iterator r;
00197 r = this->registrations.begin();
00198 while (r != this->registrations.end())
00199 {
00200 this->undo_registration(create_unregister_pdu(*r));
00201 r++;
00202 }
00203
00204
00205 ClosePDU closepdu(this->sessionID, reason);
00206
00207 this->connection->send(closepdu);
00208
00209
00210
00211 response = this->connection->wait_for_response(closepdu.get_packetID());
00212
00213
00214 if(response->get_error() != ResponsePDU::noAgentXError)
00215 {
00216
00217
00218
00219 }
00220 }
00221 catch(...)
00222 {
00223
00224
00225 }
00226
00227
00228 this->connection->disconnect();
00229 }
00230
00231 master_proxy::~master_proxy()
00232 {
00233
00234 this->disconnect(ClosePDU::reasonShutdown);
00235
00236
00237
00238 delete this->connection;
00239
00240
00241 if( ! this->io_service_by_user )
00242 {
00243 delete this->io_service;
00244 }
00245 }
00246
00247
00248 void master_proxy::do_registration(boost::shared_ptr<RegisterPDU> pdu)
00249 {
00250
00251 if( ! is_connected())
00252 {
00253 throw(disconnected());
00254 }
00255
00256
00257
00258 this->connection->send(*pdu);
00259
00260
00261
00262 boost::shared_ptr<ResponsePDU> response;
00263 response = this->connection->wait_for_response(pdu->get_packetID());
00264
00265
00266 switch(response->get_error())
00267 {
00268
00269
00270 case ResponsePDU::parseError:
00271
00272 throw(internal_error());
00273
00274 case ResponsePDU::notOpen:
00275
00276
00277 throw(disconnected());
00278
00279 case ResponsePDU::unsupportedContext:
00280
00281
00282 throw(internal_error());
00283
00284 case ResponsePDU::processingError:
00285
00286 throw(master_is_unable());
00287
00288 case ResponsePDU::noAgentXError:
00289
00290 break;
00291
00292
00293
00294 case ResponsePDU::duplicateRegistration:
00295 throw(duplicate_registration());
00296
00297 case ResponsePDU::requestDenied:
00298 throw(master_is_unwilling());
00299
00300 default:
00301
00302
00303
00304
00305 throw(parse_error());
00306 }
00307
00308
00309 return;
00310 }
00311
00312
00313
00314
00315
00316 void master_proxy::register_subtree(oid subtree,
00317 byte_t priority,
00318 byte_t timeout)
00319 {
00320
00321 boost::shared_ptr<RegisterPDU> pdu(new RegisterPDU);
00322 pdu->set_subtree(subtree);
00323 pdu->set_priority(priority);
00324 pdu->set_timeout(timeout);
00325 pdu->set_sessionID(this->sessionID);
00326
00327
00328 try
00329 {
00330 this->do_registration(pdu);
00331 }
00332 catch( internal_error )
00333 {
00334
00335
00336 throw(parse_error());
00337 }
00338 catch(...)
00339 {
00340
00341 throw;
00342 }
00343
00344
00345 this->registrations.push_back(pdu);
00346
00347 }
00348
00349
00350
00351 void master_proxy::unregister_subtree(oid subtree,
00352 byte_t priority)
00353 {
00354
00355 boost::shared_ptr<UnregisterPDU> pdu;
00356
00357
00358 std::list< boost::shared_ptr<RegisterPDU> >::iterator r;
00359 r = this->registrations.begin();
00360 while (r != this->registrations.end())
00361 {
00362 if( (*r)->get_priority() == priority
00363 && (*r)->get_subtree() == subtree
00364 && (*r)->get_range_subid() == 0
00365 && (*r)->get_upper_bound() == 0 )
00366 {
00367
00368
00369
00370 pdu = create_unregister_pdu(*r);
00371
00372
00373 r = registrations.erase(r);
00374 }
00375 else
00376 {
00377
00378 r++;
00379 }
00380 }
00381
00382
00383 try
00384 {
00385 this->undo_registration(pdu);
00386 }
00387 catch( internal_error )
00388 {
00389
00390
00391 throw(parse_error());
00392 }
00393 catch(...)
00394 {
00395
00396 throw;
00397 }
00398 }
00399
00400
00401
00402 void master_proxy::undo_registration(boost::shared_ptr<UnregisterPDU> pdu)
00403 {
00404
00405 if( ! is_connected())
00406 {
00407 throw(disconnected());
00408 }
00409
00410
00411
00412 this->connection->send(*pdu);
00413
00414
00415
00416 boost::shared_ptr<ResponsePDU> response;
00417 response = this->connection->wait_for_response(pdu->get_packetID());
00418
00419
00420 switch(response->get_error())
00421 {
00422
00423
00424 case ResponsePDU::parseError:
00425
00426 throw(internal_error());
00427
00428 case ResponsePDU::notOpen:
00429
00430
00431 throw(disconnected());
00432
00433 case ResponsePDU::unsupportedContext:
00434
00435
00436 throw(internal_error());
00437
00438 case ResponsePDU::processingError:
00439
00440 throw(master_is_unable());
00441
00442 case ResponsePDU::noAgentXError:
00443
00444 break;
00445
00446
00447
00448 case ResponsePDU::unknownRegistration:
00449 throw(unknown_registration());
00450
00451 default:
00452
00453
00454
00455
00456 throw(parse_error());
00457 }
00458
00459
00460 return;
00461 }
00462
00463
00464
00465 boost::shared_ptr<UnregisterPDU> master_proxy::create_unregister_pdu(
00466 boost::shared_ptr<RegisterPDU> pdu)
00467 {
00468 boost::shared_ptr<UnregisterPDU> new_pdu(new UnregisterPDU());
00469 new_pdu->set_subtree( pdu->get_subtree() );
00470 new_pdu->set_range_subid( pdu->get_range_subid() );
00471 new_pdu->set_upper_bound( pdu->get_upper_bound() );
00472 new_pdu->set_priority( pdu->get_priority() );
00473
00474 return new_pdu;
00475 }
00476
00477
00478
00479
00480 void master_proxy::handle_pdu(shared_ptr<PDU> pdu, int error)
00481 {
00482 if(error == -2)
00483 {
00484
00485
00486 return;
00487 }
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 ResponsePDU response;
00501 response.set_sessionID( pdu->get_sessionID() );
00502 response.set_transactionID( pdu->get_transactionID() );
00503 response.set_packetID( pdu->get_packetID() );
00504 response.set_error(ResponsePDU::noAgentXError);
00505 response.set_index(0);
00506
00507
00508
00509
00510 if(error == -1)
00511 {
00512
00513
00514
00515
00516
00517
00518
00519 response.set_error(ResponsePDU::parseError);
00520 return;
00521 }
00522
00523
00524 if(pdu->get_sessionID() != this->sessionID)
00525 {
00526 response.set_error(ResponsePDU::notOpen);
00527
00528
00529 try
00530 {
00531 this->connection->send(response);
00532 }
00533 catch(timeout_error)
00534 {
00535
00536 }
00537 catch(disconnected)
00538 {
00539
00540 }
00541
00542 return;
00543 }
00544
00545
00546
00547 shared_ptr<GetPDU> get_pdu;
00548 if( (get_pdu = dynamic_pointer_cast<GetPDU>(pdu)) != 0 )
00549 {
00550
00551
00552
00553
00554 vector<oid> sr = get_pdu->get_sr();
00555
00556
00557 vector<oid>::const_iterator i;
00558 uint16_t index = 1;
00559
00560 for(i = sr.begin(); i != sr.end(); i++)
00561 {
00562
00563 const oid& name = *i;
00564
00565
00566 map< oid, shared_ptr<variable> >::const_iterator var;
00567 var = variables.find(name);
00568 if(var != variables.end())
00569 {
00570
00571
00572
00573 try
00574 {
00575 var->second->update();
00576
00577
00578 response.varbindlist.push_back( varbind(name, var->second) );
00579 }
00580 catch(...)
00581 {
00582
00583 response.set_error( ResponsePDU::genErr );
00584 response.set_index( index );
00585
00586 }
00587
00588 }
00589 else
00590 {
00591
00592
00593
00594 oid name_copy(name, 0);
00595
00596 var = variables.find(name_copy);
00597 if(var != variables.end())
00598 {
00599
00600
00601
00602 response.varbindlist.push_back( varbind(name, varbind::noSuchInstance) );
00603 }
00604 else
00605 {
00606
00607
00608
00609 response.varbindlist.push_back( varbind(name, varbind::noSuchObject) );
00610 }
00611 }
00612
00613 index++;
00614 }
00615
00616
00617 try
00618 {
00619 this->connection->send(response);
00620 }
00621 catch(timeout_error)
00622 {
00623
00624 }
00625 catch(disconnected)
00626 {
00627
00628 }
00629 }
00630
00631
00632 }
00633
00634
00635 void master_proxy::add_variable(const oid& id, shared_ptr<variable> v)
00636 {
00637
00638 bool is_registered = false;
00639 std::list< boost::shared_ptr<RegisterPDU> >::const_iterator r;
00640 for(r = registrations.begin(); r != registrations.end(); r++)
00641 {
00642 if((*r)->get_instance_registration() == false &&
00643 (*r)->get_range_subid() == 0)
00644 {
00645
00646 if( (*r)->get_subtree().contains(id) )
00647 {
00648
00649 is_registered = true;
00650 break;
00651 }
00652 }
00653
00654 }
00655
00656 if( ! is_registered )
00657 {
00658
00659 throw(unknown_registration());
00660 }
00661 variables[id] = v;
00662 }
00663
00664
00665
00666 void master_proxy::remove_variable(const oid& id)
00667 {
00668
00669 map<oid, shared_ptr<variable> >::iterator i = variables.find(id);
00670
00671 if(i == variables.end())
00672 {
00673
00674
00675 return;
00676 }
00677
00678
00679 variables.erase(i);
00680 }