libmoost
|
00001 /* vim:set ts=3 sw=3 sts=3 et: */ 00028 // [ricky 7/13/2011 ] Mostly ripped from the nsca_send common.h file 00029 00030 #ifndef MOOST_NAGIOS_NSCA_CLIENT_NSCA_DATA_PACKET_HPP__ 00031 #define MOOST_NAGIOS_NSCA_CLIENT_NSCA_DATA_PACKET_HPP__ 00032 00033 #include <iostream> 00034 #include <string> 00035 #include <stdexcept> 00036 #include <vector> 00037 00038 #include <boost/lexical_cast.hpp> 00039 00040 #include "nsca_common.hpp" 00041 00042 namespace moost { namespace nagios { 00043 00044 struct nsca_data_packet // MUST be a POD 00045 { 00046 // for some reason the client must randomise the struct (including padding) 00047 // I can only assume this is so identical packets differ when encrypted. 00048 // Seems like overkill to me but, meh -- let's just do it for now. 00049 static void randomize(nsca_data_packet & packet) 00050 { 00051 // [ricky 7/14/2011] Just emulating what the real client does! 00052 srand((int)time(NULL)); 00053 for(size_t idx = 0 ; idx < sizeof(packet) ; idx++) 00054 { 00055 ((char *)&packet)[idx]=(int)'0'+(int)(72.0*rand()/(RAND_MAX+1.0)); 00056 } 00057 } 00058 00059 static void zeroize(nsca_data_packet & packet) 00060 { 00061 memset(&packet, 0, sizeof(packet)); 00062 } 00063 00064 boost::int16_t packet_version; 00065 boost::uint32_t crc32_value; 00066 boost::uint32_t timestamp; 00067 boost::int16_t return_code; 00068 char host_name[nsca_const::MAX_HOSTNAME_LENGTH]; 00069 char svc_description[nsca_const::MAX_DESCRIPTION_LENGTH]; 00070 char plugin_output[nsca_const::MAX_PLUGINOUTPUT_LENGTH]; 00071 }; 00072 00073 // Allow us to get a packet from a stream 00074 inline 00075 std::istream & operator >> (std::istream & os, nsca_data_packet & packet) 00076 { 00077 std::vector<std::string> lines; 00078 std::string line; 00079 while(getline(os, line) && lines.size() < 4) 00080 { 00081 lines.push_back(line); 00082 } 00083 00084 std::string errmsg; 00085 for(int check = 0 ; check >= 0 && !os.bad();) 00086 { 00087 switch(check++) 00088 { 00089 case 0: 00090 if(lines.size() != 4) 00091 { 00092 errmsg = "Payload string is malformed"; 00093 } 00094 break; 00095 case 1: 00096 if(lines[0].size() > nsca_const::MAX_HOSTNAME_LENGTH-1) 00097 { 00098 errmsg = "Hostname is too long for NSCA to handle"; 00099 } 00100 break; 00101 case 2: 00102 if(lines[1].size() > nsca_const::MAX_DESCRIPTION_LENGTH-1) 00103 { 00104 errmsg = "Service description is too long for NSCA to handle"; 00105 } 00106 break; 00107 case 3: 00108 if(lines[3].size() > nsca_const::MAX_PLUGINOUTPUT_LENGTH-1) 00109 { 00110 errmsg = "Servcice description is too long for NSCA to handle"; 00111 } 00112 break; 00113 default: 00114 check = -1; // no more checks. 00115 break; 00116 } 00117 00118 if(!errmsg.empty()) 00119 { 00120 // Oops, something's wrong 00121 os.setstate(std::ios::failbit); 00122 00123 // If the caller is expecting exceptions for this 00124 // stream give them what they asked for. 00125 if((os.exceptions() & std::ios::failbit) == std::ios::failbit) 00126 { 00127 throw std::invalid_argument(errmsg); 00128 } 00129 } 00130 } 00131 00132 // All good? 00133 if(!os.bad()) 00134 { 00135 strcpy(packet.host_name, lines[0].c_str()); 00136 strcpy(packet.svc_description, lines[1].c_str()); 00137 strcpy(packet.plugin_output, lines[3].c_str()); 00138 packet.return_code = boost::lexical_cast<boost::int16_t>(lines[2]); 00139 } 00140 00141 return os; 00142 } 00143 00144 }} 00145 00146 #endif