/* * Copyright 2016 Bjango Pty Ltd. All rights reserved. * Copyright 2010 William Tisäter. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. The name of the copyright holder may not be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL WILLIAM TISÄTER BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #include #include #include #include #include #include #include "System.h" #include "Responses.h" #include "Stats.h" #include "Utility.h" using namespace std; string encodeForXml(string sSrc) { ostringstream sRet; for( string::const_iterator iter = sSrc.begin(); iter!=sSrc.end(); iter++ ) { unsigned char c = (unsigned char)*iter; switch( c ) { case '&': sRet << "&"; break; case '<': sRet << "<"; break; case '>': sRet << ">"; break; case '"': sRet << """; break; case '\'': sRet << "'"; break; default: if ( c<32 || c>127 ) { sRet << "&#" << (unsigned int)c << ";"; } else { sRet << c; } } } return sRet.str(); } string isr_create_header() { return ""; } string isr_accept_code() { stringstream temp; temp << isr_create_header() << ""; return temp.str(); } string isr_reject_code() { stringstream temp; temp << isr_create_header() << ""; return temp.str(); } string isr_serverinfo(int session, int auth, string uuid, bool historyEnabled) { int history = 0; #ifdef USE_SQLITE if(historyEnabled == true) history = 1; #endif stringstream temp; temp << isr_create_header() << ""; return temp.str(); } string isr_accept_connection() { stringstream temp; temp << isr_create_header() << ""; return temp.str(); } string isr_cpu_data(xmlNodePtr node, Stats *stats) { #ifdef USE_CPU_NONE return ""; #endif stringstream output; char *identifiers = (char *)xmlGetProp(node, (const xmlChar *)"samples"); vector identifierItems = explode(string(identifiers), "|"); for(uint x = 0;x < identifierItems.size(); x++) { double sampleID = to_double(identifierItems[x].c_str()); deque samples; for(size_t i = 0;i < stats->cpuStats.samples[x].size(); i++) { cpu_data sample = stats->cpuStats.samples[x][i]; if (sample.sampleID > sampleID) { samples.push_front(sample); } else break; } output << "cpuStats.session << "\" id=\"" << stats->cpuStats.sampleIndex[x].sampleID << "\" threads=\"" << stats->processStats.threadCount << "\" tasks=\"" << stats->processStats.processCount << "\" samples=\"" << samples.size() << "\">"; for(size_t i = 0;i < samples.size(); i++) { struct cpu_data sample = samples[i]; output << "cpuStats.hasLpar) output << " ent=\"" << sample.ent << "\" phys=\"" << sample.phys << "\""; #endif output << ">"; } output << ""; } free(identifiers); return output.str(); } string isr_memory_data(xmlNodePtr node, Stats *stats) { #ifdef USE_MEM_NONE return ""; #endif stringstream output; char *identifiers = (char *)xmlGetProp(node, (const xmlChar *)"samples"); vector identifierItems = explode(string(identifiers), "|"); for(uint x = 0;x < identifierItems.size(); x++) { double sampleID = to_double(identifierItems[x].c_str()); deque samples; for(size_t i = 0;i < stats->memoryStats.samples[x].size(); i++) { mem_data sample = stats->memoryStats.samples[x][i]; if (sample.sampleID > sampleID) { samples.push_front(sample); } else break; } output << "memoryStats.session << "\" id=\"" << stats->memoryStats.sampleIndex[x].sampleID << "\" samples=\"" << samples.size() << "\">"; for(size_t i = 0;i < samples.size(); i++) { struct mem_data mem = samples[i]; output << "= 0) output << " file=\"" << mem.values[memory_value_file] << "\""; if(mem.values[memory_value_ex] >= 0) output << " ex=\"" << mem.values[memory_value_ex] << "\""; if(mem.values[memory_value_buffer] >= 0) output << " buf=\"" << mem.values[memory_value_buffer] << "\""; if(mem.values[memory_value_used] >= 0) output << " u=\"" << mem.values[memory_value_used] << "\""; if(mem.values[memory_value_wired] >= 0) output << " w=\"" << mem.values[memory_value_wired] << "\""; if(mem.values[memory_value_cached] >= 0) output << " ca=\"" << mem.values[memory_value_cached] << "\""; if(mem.values[memory_value_active] >= 0) output << " a=\"" << mem.values[memory_value_active] << "\""; if(mem.values[memory_value_inactive] >= 0) output << " i=\"" << mem.values[memory_value_inactive] << "\""; if(mem.values[memory_value_free] >= 0) output << " f=\"" << mem.values[memory_value_free] << "\""; if(mem.values[memory_value_total] >= 0) output << " t=\"" << mem.values[memory_value_total] << "\""; if(mem.values[memory_value_swapused] >= 0) output << " su=\"" << mem.values[memory_value_swapused] << "\""; if(mem.values[memory_value_swaptotal] >= 0) output << " st=\"" << mem.values[memory_value_swaptotal] << "\""; if(mem.values[memory_value_swapin] >= 0) output << " pi=\"" << mem.values[memory_value_swapin] << "\""; if(mem.values[memory_value_swapin] >= 0) output << " po=\"" << mem.values[memory_value_swapout] << "\""; if(mem.values[memory_value_virtualtotal] >= 0) output << " vt=\"" << mem.values[memory_value_virtualtotal] << "\""; if(mem.values[memory_value_virtualactive] >= 0) output << " va=\"" << mem.values[memory_value_virtualactive] << "\""; output << ">"; } output << ""; } free(identifiers); return output.str(); } string keyForIndex(string uuid, int index) { stringstream skey; skey << index << ":" << uuid; string key = skey.str(); return key; } string isr_network_data(int index, long sampleID, StatsNetwork stats, vector keys, vector *added) { stringstream output; output << ""; for(size_t itemindex = 0;itemindex < stats._items.size(); itemindex++) { network_info item = stats._items[itemindex]; if(!item.active) continue; if(!shouldAddKey(index, item.device, keys, added)) continue; deque samples; for(size_t i = 0;i < item.samples[index].size(); i++) { net_data sample = item.samples[index][i]; if (sample.sampleID > sampleID) { samples.push_front(sample); } else break; } output << " 0) addresses += ","; addresses += item.addresses[i]; } output << " name=\"" << encodeForXml(item.device) << "\" ip=\"" << encodeForXml(addresses) << "\" d=\"" << item.last_down << "\" u=\"" << item.last_up << "\""; } output << ">"; for(size_t i = 0;i < samples.size(); i++) { struct net_data sample = samples[i]; output << ""; } output << ""; } output << ""; return output.str(); } bool shouldAddKey(int index, string key, vector keys, vector *added) { bool add = true; string k = keyForIndex(key, index); for(size_t i = 0;i < added->size(); i++) { if(added->at(i) == k) { add = false; break; } } if(add == true && keys.size() > 0) { add = false; for(size_t i = 0;i < keys.size(); i++) { if(keys[i] == key) { add = true; break; } } } if(add == true) { added->push_back(k); } return add; } string isr_multiple_data(xmlNodePtr node, Stats *stats) { stringstream output; vector addedKeys; char *type = (char *)xmlGetProp(node, (const xmlChar *)"type"); xmlNodePtr child = node->children; while (child){ char *identifiers = (char *)xmlGetProp(child, (const xmlChar *)"samples"); char *keys = (char *)xmlGetProp(child, (const xmlChar *)"keys"); vector identifierItems = explode(string(identifiers), "|"); vector keyItems; if(keys != NULL) keyItems = explode(string(keys), "|"); for(uint x = 0;x < identifierItems.size(); x++) { double sampleID = to_double(identifierItems[x].c_str()); if(strcmp(type, "network") == 0) output << isr_network_data(x, sampleID, stats->networkStats, keyItems, &addedKeys); else if(strcmp(type, "diskactivity") == 0) output << isr_activity_data(x, sampleID, stats->activityStats, keyItems, &addedKeys); else if(strcmp(type, "sensors") == 0) output << isr_sensor_data(x, sampleID, stats->sensorStats, keyItems, &addedKeys); else if(strcmp(type, "disks") == 0) output << isr_disk_data(x, sampleID, stats->diskStats, keyItems, &addedKeys); else if(strcmp(type, "processes") == 0) output << isr_process_data(x, sampleID, stats->processStats, keyItems, &addedKeys); else if(strcmp(type, "battery") == 0) output << isr_battery_data(x, sampleID, stats->batteryStats, keyItems, &addedKeys); } if(keys != NULL) free(keys); free(identifiers); child = child->next; } free(type); return output.str(); } string isr_activity_data(int index, long sampleID, StatsActivity stats, vector keys, vector *added) { stringstream output; output << ""; for(size_t itemindex = 0;itemindex < stats._items.size(); itemindex++) { activity_info item = stats._items[itemindex]; if(!item.active) continue; if(!shouldAddKey(index, item.device, keys, added)) continue; deque samples; for(size_t i = 0;i < item.samples[index].size(); i++) { activity_data sample = item.samples[index][i]; if (sample.sampleID > sampleID) { samples.push_front(sample); } else break; } output << " 0) { output << " mounts=\""; unsigned int x; for(x=0;x 0) output << ","; output << item.mounts[x]; } output << "\""; } } output << ">"; for(size_t i = 0;i < samples.size(); i++) { struct activity_data sample = samples[i]; output << ""; } output << ""; } output << ""; return output.str(); } string isr_disk_data(int index, long sampleID, StatsDisks stats, vector keys, vector *added) { stringstream output; output << ""; for(size_t itemindex = 0;itemindex < stats._items.size(); itemindex++) { disk_info item = stats._items[itemindex]; if(!item.active) continue; if(!shouldAddKey(index, item.key, keys, added)) continue; deque samples; for(size_t i = 0;i < item.samples[index].size(); i++) { disk_data sample = item.samples[index][i]; if (sample.sampleID > sampleID) { samples.push_front(sample); } else break; } output << ""; for(size_t i = 0;i < samples.size(); i++) { struct disk_data sample = samples[i]; output << ""; } output << ""; } output << ""; return output.str(); } string isr_uptime_data(long uptime) { #ifdef USE_UPTIME_NONE return ""; #endif stringstream temp; temp << ""; return temp.str(); } string isr_loadavg_data(xmlNodePtr node, Stats *stats) { #ifdef USE_LOAD_NONE return ""; #endif stringstream output; char *identifiers = (char *)xmlGetProp(node, (const xmlChar *)"samples"); vector identifierItems = explode(string(identifiers), "|"); for(uint x = 0;x < identifierItems.size(); x++) { double sampleID = to_double(identifierItems[x].c_str()); deque samples; for(size_t i = 0;i < stats->loadStats.samples[x].size(); i++) { load_data sample = stats->loadStats.samples[x][i]; if (sample.sampleID > sampleID) { samples.push_front(sample); } else break; } output << "loadStats.session << "\" id=\"" << stats->loadStats.sampleIndex[x].sampleID << "\" samples=\"" << samples.size() << "\">"; for(size_t i = 0;i < samples.size(); i++) { load_data sample = samples[i]; output << ""; } output << ""; } free(identifiers); return output.str(); } string isr_sensor_data(int index, long sampleID, StatsSensors stats, vector keys, vector *added) { stringstream output; output << ""; for(size_t itemindex = 0;itemindex < stats._items.size(); itemindex++) { sensor_info item = stats._items[itemindex]; if(!shouldAddKey(index, item.key, keys, added)) continue; deque samples; for(size_t i = 0;i < item.samples[index].size(); i++) { sensor_data sample = item.samples[index][i]; if (sample.sampleID > sampleID) { samples.push_front(sample); } else break; } output << ""; for(size_t i = 0;i < samples.size(); i++) { struct sensor_data sample = samples[i]; output << ""; } output << ""; } output << ""; return output.str(); } string isr_battery_data(int index, long sampleID, StatsBattery stats, vector keys, vector *added) { stringstream output; output << ""; for(size_t itemindex = 0;itemindex < stats._items.size(); itemindex++) { battery_info item = stats._items[itemindex]; if(!shouldAddKey(index, item.key, keys, added)) continue; output << ""; output << ""; } output << ""; return output.str(); } bool sortProcessesCPU (process_info i,process_info j) { return (j.cpu keys, vector *added) { vector _history; if(stats._items.size() > 0) { for (vector::iterator cur = stats._items.begin(); cur != stats._items.end(); ++cur) { process_info temp = *cur; _history.push_back(temp); } } stringstream output; if(_history.size() > 0) { output << ""; if(shouldAddKey(0, "cpu", keys, added)) { std::sort (_history.begin(), _history.end(), sortProcessesCPU); int count = 0; for (vector::iterator cur = _history.begin(); cur != _history.end(); ++cur) { output << "pid << "\" c=\"" << cur->cpu << "\" name=\"" << encodeForXml(string(cur->name)) << "\">"; count++; if(count == 20) break; } } if(shouldAddKey(0, "memory", keys, added)) { int count = 0; std::sort (_history.begin(), _history.end(), sortProcessesMemory); for (vector::iterator cur = _history.begin(); cur != _history.end(); ++cur) { output << "pid << "\" m=\"" << cur->memory << "\" name=\"" << encodeForXml(string(cur->name)) << "\">"; count++; if(count == 20) break; } } /* if(keys.find("disks") != std::string::npos) { int count = 0; std::sort (_history->begin(), _history->end(), sortProcessesIORead); for (vector::iterator cur = _history->begin(); cur != _history->end(); ++cur) { temp << "pid << "\" r=\"" << cur->io_read << "\" w=\"" << cur->io_write << "\" name=\"" << cur->name << "\">"; count++; if(count == 10) break; } count = 0; std::sort (_history->begin(), _history->end(), sortProcessesIOWrite); for (vector::iterator cur = _history->begin(); cur != _history->end(); ++cur) { temp << "pid << "\" r=\"" << cur->io_read << "\" w=\"" << cur->io_write << "\" name=\"" << cur->name << "\">"; count++; if(count == 10) break; } }*/ output << ""; } else { output << ""; } return output.str(); }