00001
00057 #ifndef MD_COMMON
00058 #define MD_COMMON
00059
00060 #include<boost/asio/datagram_socket_service.hpp>
00061
00062 using namespace std;
00063 using boost::asio::ip::udp;
00064
00065 #define MAX_CLIENTS 1000
00066 #define MAX_CLIEVER 10
00067 #define MAX_DATACLIENTS 200
00068 #define MAX_INSTRUMENTS 3 // Per Cliever cluster.
00069 #define MAX_DEBUG 1000 // Set the config parm higher than this to inhibit logNdebug(m...) where m < this
00070 #define MAX_DEVICE (((MAX_CLIEVER + 1) * MAX_INSTRUMENTS) + MAX_DATACLIENTS)
00071 #ifndef MD_STAGE
00072 #define CD_DEFAULT_IP "192.168.0.9"
00073 #define MD_DEFAULT_IP "192.168.0.5"
00074 #define PULL_MD_LOG "cp /somejuan/tmp/auc-md.log ."
00075 #else
00076 #define CD_DEFAULT_IP "184.168.64.86"
00077 #define MD_DEFAULT_IP "178.79.142.228"
00078 #define PULL_MD_LOG ("scp daclips@" MD_DEFAULT_IP "/tmp/auc-md.log .")
00079 #endif
00080 #define MD_EPOCH date()
00081 #define MD_HEARTBEAT 1 // Network peer heartbeat in seconds.
00082 #define MD_MAX_DATAGRAM (32*1024) // half of the IPV4 max
00083 #define DACLIPS_APP "Generic"
00084 #define MD_COMPONENT "Master Daemon" // DACLIPS Component
00085 #define MD_NAME DACLIPS_APP " " MD_COMPONENT
00086 #define MD_VERSION " 1.1 " // DACLIPS Version
00087 #define MD_REFRESH 10 // default milliseconds between telemetry frame updates
00088 #define MD_TYPE "CENTRIFUGE" // i.e. what a MACHINE is, Change per your DACLIPS derivation
00089 #define NORMAL_DEBUG 10
00090 #ifndef CURRENT_DEBUG
00091 #define CURRENT_DEBUG NORMAL_DEBUG
00092 #endif
00093 #define NOT_OK -1
00094 #define OK 0
00095 #define RUNNING_DIR "/tmp"
00096
00097 #define theMachine thisConfig->machine[thisConfig->thisMachineContext]
00098
00099 enum md_mand {
00100 MD_NAM,
00101 MD_USER_MAND,
00102 MD_SCPI,
00103 MD_RULE_ACTION,
00104 MD_CLIEVER_CMD,
00105 MD_CLIENT_CMD,
00106 MD_NMANDS
00107 };
00108
00109 enum mdErrorCode {
00110 MDERR_OK,
00111 MDERR_MISSING,
00112 MDERR_EXISTS,
00113 MDERR_CONFLICT,
00114 MDERR_NOTREADY,
00115 MDERR_SYNTAX,
00116 N_MDSTDERR
00117 };
00118
00119 enum md_dispatch_category {
00120 MD_NEWBORN = 0,
00121 CD_FRAME,
00122 MD_FRAME,
00123 DV_MDQUERY,
00124 DVMDQ_REGSCPI,
00125 DVMDQ_REGOBS,
00126 DVMDQ_REGODE,
00127 MD_SHUTDOWN
00128 };
00129
00130 enum md_device {
00131 MDDEV_MD = 0,
00132 MDDEV_CD,
00133 MACHINE,
00134 MDDEV_INSTRUMENT,
00135 MDDEV_DATACLIENT,
00136 N_MDDEV_TYPES
00137 };
00138
00139 enum md_units {
00140 MD_UNITS_UNDEFINED = 0,
00141 MD_CENTIMETERS,
00142 MD_MILLIMETERS,
00143 MD_MICRONS,
00144 MD_NANOMETERS,
00145 MD_VOLTS,
00146 MD_CC,
00147 N_MD_UNITS
00148 };
00149
00150 enum mdDGtype {
00151 MDDG_HEARTBEAT = 0,
00152 MDDG_DEVICEHB,
00153 MDDG_NEWBORN,
00154 MDDG_MDQUERY,
00155 MDDG_REGSCPI,
00156 MDDG_REGOBS,
00157 MDDG_REGODE,
00158 MDDG_TELEMETRY,
00159 MDDG_CDRESET,
00160 N_MDDG_TYPES
00161 };
00162
00163 typedef
00164 struct MD_DG_TYPE {
00165 unsigned inBandOnly : 1;
00166 unsigned requiresAck : 1;
00167 unsigned isAckNak : 1;
00168 unsigned value : 1;
00169 unsigned reserved : 4;
00170 unsigned clieverGroup : 8;
00171 unsigned reserved2 : 16;
00172 }
00173 mdDGflags;
00174
00175 typedef
00176 struct MD_DG_HEADER {
00177 mdDGtype msgType;
00178 mdDGflags dgType;
00179 mdDGtype dgSubType;
00180 int msgSN;
00181 md_device clientType;
00182 int sourceHandle;
00183 int sinkHandle;
00184 int handle;
00185 mdErrorCode ec;
00186 int payloadSize;
00187 int primeOffset;
00188 }
00189 mdDGHeader;
00190
00191 typedef
00192 struct MD_DATAGRAM {
00193 mdDGHeader hdr;
00194 char payLoad[MD_MAX_DATAGRAM - (sizeof(mdDGHeader))];
00195 }
00196 mdDatagram;
00197
00198 typedef
00199 struct MD_REPLY {
00200 mdDGHeader hdr;
00201 char payLoad[512 - sizeof(mdDGHeader)];
00202 }
00203 mdDGReply;
00204
00205 class mdReply {
00206 public:
00207
00208 mdDGReply dg;
00209
00210 mdReply() {memset((void *)&dg,0,sizeof(mdDGReply));
00211 dg.hdr.dgType.isAckNak = true;
00212 }
00213 };
00214
00215 #if (defined(MD_MAIN) || defined(CD_MAIN) || defined(DV_MAIN) || defined(DV_DLL_MAIN))
00216 const char *clientTypes[N_MDDEV_TYPES ] = { "Master Daemon", "Cliever", "Machine", "Instrument", "MD Non-Data Client" };
00217 #else
00218 extern const char *clientTypes[N_MDDEV_TYPES];
00219 #endif
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 class mdWQitem {
00231 public:
00232 md_dispatch_category kind;
00233 const void *what;
00234 int user;
00235 mdWQitem (const void *work,md_dispatch_category priority,int x)
00236 : what(work), kind(priority), user(x) {}
00237
00238 bool operator< (const mdWQitem & right) const {
00239 return kind < right.kind;
00240 }
00241
00242 };
00243
00244 typedef std::priority_queue < mdWQitem* > MDWQ;
00245
00246 class mdProcess {
00247 public: MDWQ q;
00248 mdProcess() {}
00249 ~mdProcess() {}
00250
00251 void queue(mdWQitem *w) {q.push(w);}
00252 virtual void dispatch(mdWQitem *w)=0;
00253 virtual void run() = 0;
00254
00255 };
00256 #define MD_DEFAULT_DEVICE_PROTOCOL 0
00257 #define MD_DEFAULT_RULE 0
00258
00259 typedef
00260 struct {
00261 unsigned open:1;
00262 unsigned looped:1;
00263 unsigned reserved:30;
00264 } mdCnctBool;
00265
00266 typedef
00267 struct MD_CONTROL_BLOCK
00268 {int handle;
00269 mdCnctBool connection;
00270 boost::asio::ip::udp::endpoint ep;
00271 boost::asio::ip::udp::resolver::iterator it;
00272 boost::asio::ip::udp::socket *udp;
00273 MD_CONTROL_BLOCK() {
00274 handle = 0;
00275 memset((void *)&connection,0,sizeof(connection));
00276 udp = NULL;
00277 }
00278 }
00279 mdCB;
00280
00281 typedef std::map<int,mdCB*> mdStdDevicePODMap;
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 #if (defined(MD_MAIN) || defined(CD_MAIN) || defined(DV_DLL_MAIN))
00294 mdStdDevicePODMap cb;
00295 int myStdDevIdx=MAX_CLIENTS+1;
00296 #else
00297 extern mdStdDevicePODMap cb;
00298 extern int myStdDevIdx;
00299 #endif
00300
00301 class mdDGChannel
00302 {public:
00303
00304 boost::asio::io_service& io_service_;
00305 boost::asio::ip::udp::endpoint p_endpoint_;
00306 boost::asio::ip::udp::endpoint a_endpoint_;
00307 boost::asio::ip::udp::endpoint *ep_;
00308 boost::asio::ip::udp::resolver *r;
00309 boost::asio::ip::udp::resolver::query *q;
00310 boost::asio::ip::udp::socket passive_;
00311 boost::asio::ip::udp::socket *active_;
00312 boost::asio::ip::udp::socket *s_;
00313
00314 char ack_[sizeof(mdDGReply)];
00315 char data_[MD_MAX_DATAGRAM];
00316
00317 int mdStdDevIdx;
00318
00319 mdDatagram *inProcess;
00320 mdReply *reply;
00321
00322 short port;
00323
00324 mdDGChannel(boost::asio::io_service& io_service,
00325 short inport, int stdDevIdx=myStdDevIdx)
00326 : io_service_(io_service), mdStdDevIdx(stdDevIdx),
00327 passive_(io_service, udp::endpoint(udp::v4(), inport))
00328 {
00329 inProcess = (mdDatagram *)data_;
00330 ep_ = &p_endpoint_;
00331 port = inport;
00332 reply = (mdReply *)ack_;
00333 q = NULL;
00334 r = NULL;
00335 s_ = &passive_;
00336
00337 passive_.async_receive_from(
00338 boost::asio::buffer(data_, MD_MAX_DATAGRAM), p_endpoint_,
00339 boost::bind(&mdDGChannel::handle_receive_from, this,
00340 boost::asio::placeholders::error,
00341 boost::asio::placeholders::bytes_transferred));
00342 }
00343
00344 void async_send(mdDatagram &dg) {
00345
00346 size_t dgSize = sizeof(mdDGHeader) + dg.hdr.payloadSize;
00347
00348 *inProcess = dg;
00349
00350
00351 active_->async_send_to(
00352 boost::asio::buffer(data_, dgSize), *ep_,
00353 boost::bind(&mdDGChannel::handle_send_to, this,
00354 boost::asio::placeholders::error,
00355 boost::asio::placeholders::bytes_transferred));
00356 }
00357
00358 bool connect_to (std::string &host, std::string &port, int stdDevIdx=-1) {
00359
00360 bool value = false;
00361 int rport = atoi(port.c_str());
00362 boost::system::error_code ec;
00363 boost::asio::ip::udp::endpoint remote ( boost::asio::ip::address::from_string(host.c_str()), rport);
00364
00365 stdDevIdx = (stdDevIdx == -1) ? mdStdDevIdx : stdDevIdx;
00366 map<int,mdCB *>::iterator iter = cb.find(stdDevIdx);
00367 if( iter == cb.end() ) cb[stdDevIdx] = new mdCB();
00368
00369 try {
00370 if (!r) r = new udp::resolver(io_service_);
00371 if ( q) delete q;
00372 q = new udp::resolver::query(udp::v4(), host.c_str(), port.c_str());
00373 cb[stdDevIdx]->it = r->resolve(*q);
00374 if (!cb[mdStdDevIdx]->udp)
00375 cb[mdStdDevIdx]->udp = new udp::socket(io_service_, udp::endpoint(udp::v4(), 0));
00376 active_ = cb[mdStdDevIdx]->udp;
00377 if (active_->is_open())
00378 active_->connect(remote,ec);
00379
00380 if (!ec) value = true;
00381
00382 } catch(...) {}
00383
00384 return (cb[stdDevIdx]->connection.open=value);
00385
00386 }
00387
00388 bool connect_to (boost::asio::ip::udp::endpoint &ep,boost::system::error_code &ec,int &step,int stdDevIdx=-1)
00389 {
00390
00391 bool value = false;
00392
00393 stdDevIdx = stdDevIdx == -1 ? mdStdDevIdx : stdDevIdx;
00394 map<int,mdCB *>::iterator iter = cb.find(stdDevIdx);
00395 if( iter == cb.end() ) cb[stdDevIdx] = new mdCB();
00396
00397 try { if (cb[stdDevIdx]->udp) {if (cb[stdDevIdx]->udp->is_open())
00398 cb[stdDevIdx]->udp->close();
00399 delete cb[stdDevIdx]->udp;}
00400
00401 cb[stdDevIdx]->ep = ep;
00402 active_ = cb[stdDevIdx]->udp = new boost::asio::ip::udp::socket( io_service_ , udp::endpoint(udp::v4(), 0) );
00403 ec.clear();
00404 active_->connect( cb[stdDevIdx]->ep, ec );
00405 if (active_->is_open()) { value = true; cb[stdDevIdx]->connection.open=1; }
00406 else {
00407 step++;
00408 active_->open( udp::v4(), ec );
00409 if (active_->is_open()) {value = true; cb[stdDevIdx]->connection.open=1; }
00410 }
00411
00412 }
00413 catch(boost::system::system_error &be) {boost::system::system_error warning = be;}
00414 catch(...) {}
00415
00416 return (value);
00417
00418 }
00419
00420 void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd);
00421
00422 void handle_send_to(const boost::system::error_code& asioEC, size_t sentByes)
00423 {
00424 size_t dgSize = inProcess->hdr.dgType.requiresAck
00425 ? sizeof(mdReply) : sizeof(mdDatagram);
00426
00427
00428
00429 if (inProcess->hdr.dgType.requiresAck)
00430 active_->async_receive_from(
00431 boost::asio::buffer(ack_, dgSize), *ep_,
00432 boost::bind(&mdDGChannel::handle_receive_from, this,
00433 boost::asio::placeholders::error,
00434 boost::asio::placeholders::bytes_transferred));
00435 else
00436 active_->async_receive_from(
00437 boost::asio::buffer(data_, dgSize), *ep_,
00438 boost::bind(&mdDGChannel::handle_receive_from, this,
00439 boost::asio::placeholders::error,
00440 boost::asio::placeholders::bytes_transferred));
00441 }
00442
00443 bool send(mdDatagram &dg) {
00444
00445 size_t dgSize = sizeof(mdDGHeader) + dg.hdr.payloadSize;
00446
00447 return (dgSize ==
00448 active_->send(boost::asio::buffer((void *)&dg, dgSize)));
00449
00450 }
00451
00452 bool send_to(mdDatagram &dg, int mdStdDevIdx) {
00453
00454 size_t dgSize = sizeof(mdDGHeader) + dg.hdr.payloadSize;
00455
00456 return (dgSize ==
00457 active_->send_to(boost::asio::buffer((void *)&dg, dgSize), *cb[mdStdDevIdx]->it));
00458
00459 }
00460
00461 size_t send(mdReply &dg, boost::system::error_code &ec) {
00462
00463 size_t dgSize = sizeof(mdDGReply);
00464 boost::asio::socket_base::message_flags flags=0;
00465
00466 return (active_->send(boost::asio::buffer((void *)&dg, dgSize), flags, ec));
00467
00468 }
00469
00470 size_t send_back(mdReply &dg, boost::system::error_code &ec, int &step) {
00471
00472 size_t dgSize = sizeof(mdDGReply);
00473 boost::asio::socket_base::message_flags flags=0;
00474 step = 1;
00475
00476 a_endpoint_ = passive_.remote_endpoint(ec);
00477
00478 if (ec) return 0;
00479
00480 return (passive_.send_to(boost::asio::buffer((void *)&dg, dgSize), a_endpoint_, flags, ec));
00481
00482 }
00483
00484 bool send_to(mdReply &dg,int mdStdDevIdx) {
00485
00486 size_t dgSize = sizeof(mdDGReply);
00487
00488 return (dgSize ==
00489 active_->send_to(boost::asio::buffer((void *)&dg, dgSize), *cb[mdStdDevIdx]->it));
00490
00491 }
00492
00493 };
00494
00495
00496 #if defined(_WIN32_WINNT) && !defined(DllExport) && defined(DV_DLL)
00497 #pragma warning( disable: 4251 )
00498 #define DllExport __declspec(dllexport)
00499 #else
00500 #define DllExport
00501 #endif
00502
00503 typedef std::map<int,std::string> mdErrMsgMap;
00504
00505 class DllExport mdError {
00506
00507 int instance;
00508 mdErrMsgMap text;
00509
00510 public:
00511 mdError() { text[0] = std::string("OK");
00512 instance = 0;
00513 }
00514
00515 ~mdError() {}
00516
00517
00518
00519
00520
00521
00522 void additionalUserMsg(int instCode,const char *msgText)
00523 {if (instCode >= 1000) text[instCode] = std::string(msgText);}
00524 void additionalSystemMsg(int instCode,const char *msgText)
00525 {if (instCode < 1000 && instCode >0) text[instCode] = std::string(msgText);}
00526
00527 int get() {return instance;}
00528 void get(mdError **parentPtr)
00529 {*parentPtr = this;}
00530 void set(int i) {instance = i;}
00531
00532 const char *what(char *buffer=NULL) {
00533 if (text.find(get()) == text.end()) {
00534 {if (!buffer) return NULL;
00535 sprintf(buffer,"Unknown error code: %d",get());
00536 return buffer;
00537 }
00538 return text[get()].c_str();
00539 }
00540 return "unknown";
00541 }
00542
00543 };
00544
00545 class mdDG {
00546 public:
00547 mdDatagram dg;
00548
00549 mdDG() {memset(&dg,0,sizeof(mdDatagram));}
00550
00551 };
00552
00553 #endif