Also moved all of the Host C++ code to C APIs. Refactored the Multiplexer and Datahandler APIs. Rewrote the unit tests to all use Check rather than CPPUnit.
Removed the host API tests since they no longer applied.
Signed-off-by: Darryl L. Pierce dpierce@redhat.com --- .gitignore | 1 + bootstrap.conf | 3 + configure.ac | 2 +- src/Makefile.am | 22 ++- src/host.c | 384 ++++++++++++++++++++++++++++++++++ src/host.cpp | 123 ----------- src/host.h | 45 +++-- src/linux_platform.cpp | 174 ---------------- src/linux_platform.h | 34 --- src/main.cpp | 20 ++- src/platform.cpp | 36 ---- src/platform.h | 77 ------- src/qmf/hostagent.cpp | 7 +- src/qmf/hostagent.h | 3 +- src/tests/Makefile.am | 38 ++-- src/tests/testdatahandler.c | 255 +++++++++++++++++++++++ src/tests/testhostapis.h | 54 ----- src/tests/testmultiplexer.c | 179 ++++++++++++++++ src/tests/testmultiplexer.cpp | 110 ---------- src/tests/testmultiplexer.h | 46 ---- src/utils.c | 64 ++++++ src/utils.h | 37 ++++ src/virtio/datahandler.c | 268 ++++++++++++++++++++++++ src/virtio/datahandler.h | 61 ++++++ src/virtio/lib_crc.c | 459 +++++++++++++++++++++++++++++++++++++++++ src/virtio/lib_crc.h | 66 ++++++ src/virtio/multiplexer.c | 122 +++++++++++ src/virtio/multiplexer.cpp | 62 ------ src/virtio/multiplexer.h | 46 +++-- 29 files changed, 2004 insertions(+), 794 deletions(-) create mode 100644 src/host.c delete mode 100644 src/host.cpp delete mode 100644 src/linux_platform.cpp delete mode 100644 src/linux_platform.h delete mode 100644 src/platform.cpp delete mode 100644 src/platform.h create mode 100644 src/tests/testdatahandler.c delete mode 100644 src/tests/testhostapis.h create mode 100644 src/tests/testmultiplexer.c delete mode 100644 src/tests/testmultiplexer.cpp delete mode 100644 src/tests/testmultiplexer.h create mode 100644 src/utils.c create mode 100644 src/utils.h create mode 100644 src/virtio/datahandler.c create mode 100644 src/virtio/datahandler.h create mode 100644 src/virtio/lib_crc.c create mode 100644 src/virtio/lib_crc.h create mode 100644 src/virtio/multiplexer.c delete mode 100644 src/virtio/multiplexer.cpp
diff --git a/.gitignore b/.gitignore index e4935e0..5221238 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ *.patch *~ .deps +.magentdata /GNUmakefile /maint.mk Makefile diff --git a/bootstrap.conf b/bootstrap.conf index 8d602c1..9157db4 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -18,6 +18,9 @@ # gnulib modules used by this package. gnulib_modules=" maintainer-makefile +malloc +stdbool +strcspn strdup-posix "
diff --git a/configure.ac b/configure.ac index 9fda954..1dfdd80 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ dnl ---------------------------------------------------------------------
AC_PREREQ([2.65]) AC_INIT([Matahari], [0.1.0], [matahari@lists.fedorahosted.org]) -AC_CONFIG_SRCDIR([src/linux_platform.cpp]) +AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([src/config.h]) AC_CONFIG_MACRO_DIR([m4]) diff --git a/src/Makefile.am b/src/Makefile.am index 20532b0..aac6fec 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,8 @@ -NCLUDES = -I$(top_builddir)/lib -I$(top_srcdir)/lib -I$(top_srcdir)/src/qmf/com/redhat/matahari $(LIBVIRT_CFLAGS) $(PCRE_CFLAGS) $(UDEV_CFLAGS) +INCLUDES = \ + -I$(top_builddir)/lib \ + -I$(top_srcdir)/lib \ + -I$(top_srcdir)/src/qmf/com/redhat/matahari \ + -I/usr/include/libxml2
AM_CFLAGS = $(INCLUDES) AM_CXXFLAGS = $(INCLUDES) @@ -17,17 +21,19 @@ generated_file_list = \ nodist_matahari_SOURCES = $(generated_file_list) $(first)
matahari_SOURCES = \ - host.cpp \ + host.c \ host.h \ hostlistener.h \ - linux_platform.cpp \ - linux_platform.h \ main.cpp \ - platform.cpp \ - platform.h \ + utils.c \ + utils.h \ qmf/hostagent.cpp \ qmf/hostagent.h \ - virtio/multiplexer.cpp \ + virtio/datahandler.c \ + virtio/datahandler.h \ + virtio/lib_crc.c \ + virtio/lib_crc.h \ + virtio/multiplexer.c \ virtio/multiplexer.h
$(generated_file_list): $(generated_file_list) @@ -39,7 +45,7 @@ BUILT_SOURCES = $(generated_file_list) $(first) CLEANFILES = $(generated_file_list) $(first)
matahari_CPPFLAGS = -fno-strict-aliasing -matahari_LDADD = -lpcre -lqmf -lqpidclient -lqpidcommon -ludev -lvirt +matahari_LDADD = -lpcre -lqmf -lqpidclient -lqpidcommon -ludev -lvirt -lxml2 matahari_LDADD += ../lib/libmatahari.a
dist_pkgdata_DATA = schema.xml diff --git a/src/host.c b/src/host.c new file mode 100644 index 0000000..9fe9b09 --- /dev/null +++ b/src/host.c @@ -0,0 +1,384 @@ +/* host.c - Copyright (C) 2009 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include <config.h> +#include "host.h" +#include <libudev.h> + +#ifdef HAVE_LIBVIRT +#include <libvirt/libvirt.h> +#endif + +#include <pcre.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/sysinfo.h> +#include <sys/utsname.h> +#include "utils.h" + +#define MAX_UUID_LENGTH 128 + +typedef struct _heartbeat_listener +{ + host_heartbeat_callback_t listener; + struct _heartbeat_listener* next; +} heartbeat_listener_t; + +typedef struct _update_listener +{ + host_update_callback_t listener; + struct _update_listener* next; +} update_listener_t; + +heartbeat_listener_t* _heartbeat_listeners = NULL; +update_listener_t* _update_listeners = NULL; +unsigned int _heartbeat_sequence = 0; +char* _cpu_model = NULL; + +void +host_register_heartbeat_listener(host_heartbeat_callback_t listener) +{ + heartbeat_listener_t* current = + (heartbeat_listener_t*)malloc(sizeof(heartbeat_listener_t)); + + current->listener = listener; + current->next = NULL; + + if(_heartbeat_listeners) + { + heartbeat_listener_t* tail = _heartbeat_listeners; + while(tail->next) tail = tail->next; + tail->next = current; + } + else + { + _heartbeat_listeners = current; + } +} + +void +host_remove_heartbeat_listener(host_heartbeat_callback_t listener) +{ + heartbeat_listener_t* current = _heartbeat_listeners; + heartbeat_listener_t* last = NULL; + + while(current) + { + if (current->listener == listener) + { + if(current == _heartbeat_listeners) + { + _heartbeat_listeners = current->next; + } + else + { + last->next = current->next; + current->next = NULL; + } + + free(current); + current = NULL; + } + else + { + last = current; + current = current->next; + } + } +} + +void +host_register_update_listener(host_update_callback_t listener) +{ + update_listener_t* current = + (update_listener_t*)malloc(sizeof(update_listener_t)); + + current->listener = listener; + current->next = NULL; + + if(_update_listeners) + { + update_listener_t* tail = _update_listeners; + while(tail->next) tail = tail->next; + tail->next = current; + } + else + { + _update_listeners = current; + } +} + +void +host_remove_update_listener(host_update_callback_t listener) +{ + update_listener_t* current = _update_listeners; + update_listener_t* last = NULL; + + while(current) + { + if (current->listener == listener) + { + if(current == _update_listeners) + { + _update_listeners = current->next; + } + else + { + last->next = current->next; + current->next = NULL; + } + + free(current); + current = NULL; + } + else + { + last = current; + current = current->next; + } + } +} + +void +host_update_event(void) +{ + time_t __time; + time(&__time); + + heartbeat_listener_t* _heartbeat_current = _heartbeat_listeners; + + while(_heartbeat_current) + { + _heartbeat_current->listener((unsigned long)time, _heartbeat_sequence); + _heartbeat_current = _heartbeat_current->next; + } + + update_listener_t* _update_current= _update_listeners; + + while(_update_current) + { + _update_current->listener(); + _update_current = _update_current->next; + } +} + +char* +host_get_uuid(void) +{ + static char* _uuid = NULL; + + if(_uuid == NULL) + { + _uuid = (char*)malloc(MAX_UUID_LENGTH); +#ifdef __linux__ + FILE* input; + + if( (input = fopen("/var/lib/dbus/machine-id", "r")) != NULL) + { + fscanf(input, "%s", _uuid); + fclose(input); + } +#else + return "UNDEFINED"; +#endif + } + + return _uuid; +} + +char* +host_get_hostname(void) +{ + char* result = NULL; + +#ifdef __linux__ + struct utsname details; + + if(!uname(&details)) + { + result = (char*)malloc(strlen(details.nodename) + 1); + strcpy(result, details.nodename); + } +#else + +#endif + + return result; +} + +char* +host_get_hypervisor(void) +{ + static char* _hypervisor = NULL; + + if(_hypervisor == NULL) + { +#ifdef HAVE_LIBVIRT + virConnectPtr lvconn = virConnectOpenReadOnly(NULL); + + if(lvconn) + { + const char* __hv = virConnectGetType(lvconn); + _hypervisor = (char*)malloc(strlen(__hv) + 1); + strcpy(_hypervisor, __hv); + virConnectClose(lvconn); + } +#endif + } + + return _hypervisor; +} + +char* +host_get_architecture(void) +{ + static char* _arch = NULL; + + if(_arch == NULL) + { +#ifdef __linux__ + struct utsname details; + + if(!uname(&details)) + { + _arch = (char*)malloc(strlen(details.machine) + 1); + strcpy(_arch, details.machine); + } +#else +#endif + } + + return _arch; +} + +unsigned int +host_get_memory(void) +{ + static int _memory = 0; + + if(!_memory) + { +#ifdef __linux__ + + struct sysinfo sysinf; + if(!sysinfo(&sysinf)) + { + _memory = sysinf.totalram / 1024L; + } + +#else + +#endif + } + + return _memory; +} + +bool +_found_cpu_model(char* line, int offset, int* matches) +{ + char* value; + + value = line + matches[1]; + _cpu_model = (char*)malloc(strlen(value) + 1); + strcpy(_cpu_model, value); + + return true; +} + +char* +host_get_cpu_model(void) +{ + if(_cpu_model == NULL) + { +#ifdef __linux__ + + search_file("/proc/cpuinfo", "model name.*:\w*(\S*)", + _found_cpu_model); + +#else + +#endif + } + return _cpu_model; +} + +unsigned int +host_get_number_of_cpu_cores(void) +{ + static unsigned int _cores = 0; + + if(_cores == 0) + { +#ifdef __linux__ + + struct udev* udev = udev_new(); + struct udev_enumerate* enumerator = udev_enumerate_new(udev); + + udev_enumerate_add_match_property(enumerator, "DRIVER", "processor"); + if(!udev_enumerate_scan_devices(enumerator)) + { + struct udev_list_entry* entries = + udev_enumerate_get_list_entry(enumerator); + struct udev_list_entry* entry; + + udev_list_entry_foreach(entry, entries) + { + _cores++; + } + } + + udev_enumerate_unref(enumerator); + udev_unref(udev); + +#else + +#endif + } + + return _cores; +} + +double +host_get_load_average(void) +{ + double result = 0.0; + +#ifdef __linux__ + + getloadavg(&result, 1); + +#else + +#endif + + return result; +} + +void +host_reboot(void) +{ +} + +void +host_shutdown(void) +{ +} diff --git a/src/host.cpp b/src/host.cpp deleted file mode 100644 index dfb83f5..0000000 --- a/src/host.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* host.cpp - Copyright (C) 2009 Red Hat, Inc. - * Written by Arjun Roy arroy@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include <config.h> -#include "host.h" - -#include "platform.h" -#include <set> - -using namespace std; - -set<HostListener*> _listeners; -unsigned int _heartbeat_sequence; - -void -host_register_listener(HostListener* listener) -{ - _listeners.insert(listener); -} - -void -host_remove_listener(HostListener* listener) -{ - _listeners.erase(listener); -} - -void -host_update_event() -{ - _heartbeat_sequence++; - - time_t __time; - time(&__time); - - for(set<HostListener*>::iterator iter = _listeners.begin(); - iter != _listeners.end(); - iter++) - { - (*iter)->heartbeat((unsigned long)__time, - _heartbeat_sequence); - } - - for(set<HostListener*>::iterator iter = _listeners.begin(); - iter != _listeners.end(); - iter++) - { - (*iter)->updated(); - } -} - -string -host_get_uuid() -{ - return Platform::instance()->getUUID(); -} - -string -host_get_hostname() -{ - return Platform::instance()->getHostname(); -} - -string -host_get_hypervisor() -{ - return Platform::instance()->getHypervisor(); -} - -string -host_get_architecture() -{ - return Platform::instance()->getArchitecture(); -} - -unsigned int -host_get_memory() -{ - return Platform::instance()->getMemory(); -} - -string -host_get_cpu_model() -{ - return Platform::instance()->getCPUModel(); -} - -unsigned int -host_get_number_of_cpu_cores() -{ - return Platform::instance()->getNumberOfCPUCores(); -} - -double -host_get_load_average() -{ - return Platform::instance()->getLoadAverage(); -} - -void -host_reboot() -{ -} - -void -host_shutdown() -{ -} diff --git a/src/host.h b/src/host.h index dab88ad..f860a76 100644 --- a/src/host.h +++ b/src/host.h @@ -20,39 +20,48 @@ * also available at http://www.gnu.org/copyleft/gpl.html. */
-#include <string> -#include <set> +#ifdef __cplusplus +extern "C" +{ +#endif
-#include "hostlistener.h" + typedef void(*host_heartbeat_callback_t)(unsigned long, unsigned int); + typedef void(*host_update_callback_t)(void);
-using namespace std; + void host_register_heartbeat_listener(host_heartbeat_callback_t listener);
-void host_register_listener(HostListener* listener); + void host_remove_heartbeat_listener(host_heartbeat_callback_t listener);
-void host_remove_istener(HostListener* listener); + void host_register_update_listener(host_update_callback_t listener);
-void host_update_event(); + void host_remove_update_listener(host_update_callback_t listener);
-string host_get_uuid(); + void host_update_event(void);
-string host_get_hostname(); + char* host_get_uuid(void);
-string host_get_hypervisor(); + char* host_get_hostname(void);
-string host_get_architecture(); + char* host_get_hypervisor(void);
-unsigned int host_get_memory(); + char* host_get_architecture(void);
-string host_get_cpu_model(); + unsigned int host_get_memory(void);
-unsigned int host_get_number_of_cpu_cores(); + char* host_get_cpu_model(void);
-double host_get_load_average(); + unsigned int host_get_number_of_cpu_cores(void);
-void host_identify(const unsigned int iterations); + double host_get_load_average(void);
-void host_shutdown(); + void host_identify(const unsigned int iterations);
-void host_reboot(); + void host_shutdown(void); + + void host_reboot(void); + +#ifdef __cplusplus +} +#endif
#endif // __HOST_H diff --git a/src/linux_platform.cpp b/src/linux_platform.cpp deleted file mode 100644 index 8b70f37..0000000 --- a/src/linux_platform.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* linux_platform.cpp - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include <config.h> -#include <fstream> -#include <iomanip> -#include <iostream> -#include <dirent.h> -#include <libvirt/libvirt.h> -#include <net/if.h> -#include <pcre.h> -#include <stdexcept> -#include <string.h> -#include <sys/ioctl.h> -#include <sys/sysinfo.h> -#include <sys/utsname.h> - -using namespace std; - -// TODO remove this wrapper once rhbz#583747 is fixed -extern "C" { -#include <libudev.h> -} - -#include "linux_platform.h" - -using namespace std; - -LinuxPlatform::LinuxPlatform() -{ - struct utsname details; - ifstream *input; - - input = new ifstream("/var/lib/dbus/machine-id"); - - if(input->is_open()) - { - string uuid; - - getline(*input, uuid); - input->close(); - delete input; - this->setUUID(uuid); - } - - if(!uname(&details)) - { - this->setHostname(string(details.nodename)); - this->setArchitecture(string(details.machine)); - } - else - { - throw runtime_error("Unable to retrieve system details"); - } - - virConnectPtr lvconn = virConnectOpenReadOnly(NULL); - - if(lvconn) - { - this->setHypervisor(string(virConnectGetType(lvconn))); - virConnectClose(lvconn); - } - - struct sysinfo sysinf; - if(!sysinfo(&sysinf)) - { - this->setMemory(sysinf.totalram / 1024L); - } - else - { - throw runtime_error("Unable to retrieve system memory details."); - } - - int cpu_count = 0; - - struct udev* udev = udev_new(); - struct udev_enumerate* enumerator = udev_enumerate_new(udev); - - udev_enumerate_add_match_property(enumerator, "DRIVER", "processor"); - if(!udev_enumerate_scan_devices(enumerator)) - { - struct udev_list_entry* entries = udev_enumerate_get_list_entry(enumerator); - struct udev_list_entry* entry; - - udev_list_entry_foreach(entry, entries) - { - cpu_count++; - } - setNumberOfCPUCores(cpu_count); - } - - udev_enumerate_unref(enumerator); - udev_unref(udev); - - input = new ifstream("/proc/cpuinfo"); - - if(input->is_open()) - { - string regexstr = "(.*\S)\s*:\s*(\S.*)"; - int expected = 3; - int found[expected * 3]; - const char* pcre_error; - int pcre_error_offset; - pcre* regex; - bool done = false; - bool started = false; - - regex = pcre_compile(regexstr.c_str(), 0, &pcre_error, &pcre_error_offset, NULL); - if(!regex) { throw runtime_error("Unable to compile regular expression."); } - - while(!input->eof() && !done) - { - string line; - - getline(*input, line); - int match = pcre_exec(regex, NULL, line.c_str(), line.length(), - 0, PCRE_NOTEMPTY,found, expected * 3); - - if(match == expected) - { - string name = line.substr(found[2], found[3] - found[2]); - string value = line.substr(found[4], found[5] - found[4]); - - // if we're at a second processor and we've already started, then we're done - if (name == "processor") - { - if (started) - { - done = true; - } - else - { - started = true; - } - } - else - { - if(name == "model name") setCPUModel(value); - } - } - } - input->close(); - delete input; - } -} - -double -LinuxPlatform::getLoadAverage() const -{ - double load_average; - ifstream input; - - input.open("/proc/loadavg", ios::in); - input >> load_average; - input.close(); - - return load_average; -} diff --git a/src/linux_platform.h b/src/linux_platform.h deleted file mode 100644 index de9664a..0000000 --- a/src/linux_platform.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef __LINUX_PLATFORM_H -#define __LINUX_PLATFORM_H - -/* linux_platform.h - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include "platform.h" - -class LinuxPlatform : public Platform -{ - public: - LinuxPlatform(); - virtual ~LinuxPlatform() {} - - virtual double getLoadAverage() const; -}; - -#endif diff --git a/src/main.cpp b/src/main.cpp index 27b2434..1748e12 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,6 +43,8 @@ using namespace qpid::client; using namespace std; namespace _qmf = qmf::com::redhat::matahari;
+HostAgent _hostAgent; + // Global Variables ManagementAgent::Singleton* singleton;
@@ -52,6 +54,17 @@ shutdown(int /*signal*/) exit(0); }
+void +send_host_heartbeat_via_qmf(unsigned long time, unsigned int sequence) +{ + _hostAgent.heartbeat(time, sequence); +} + +void send_host_update_via_qmf(void) +{ + _hostAgent.updated(); +} + static void print_usage() { @@ -80,7 +93,6 @@ main(int argc, char **argv)
ConnectionSettings settings; ManagementAgent *agent; - HostAgent hostAgent;
struct option opt[] = { {"help", no_argument, NULL, 'h'}, @@ -181,8 +193,10 @@ main(int argc, char **argv)
agent->init(settings, 5, false, ".magentdata");
- // Get the info and post it to the broker - hostAgent.setup(agent); + // setup the host agent + host_register_heartbeat_listener(send_host_heartbeat_via_qmf); + host_register_update_listener(send_host_update_via_qmf); + _hostAgent.setup(agent);
while(1) { diff --git a/src/platform.cpp b/src/platform.cpp deleted file mode 100644 index 087cf2a..0000000 --- a/src/platform.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* platform.cpp - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include <config.h> -#include "platform.h" -#include "linux_platform.h" - -Platform* Platform::_instance = 0; - -Platform* -Platform::instance() -{ - // TODO this is where we decide which implementation to use - if(!_instance) - { - _instance = new LinuxPlatform; - } - - return _instance; -} diff --git a/src/platform.h b/src/platform.h deleted file mode 100644 index 7c0eb91..0000000 --- a/src/platform.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef __PLATFORM_H -#define __PLATFORM_H - -/* platform.h - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include <string> -#include <vector> - -using namespace std; - -/* - * Platform defines a type that provides platform-specific details. - * - * Implementations provide the specific details needed by the - * various agents at runtime. - */ -class Platform -{ - private: - static Platform* _instance; - - string _uuid; - string _hostname; - string _hypervisor; - string _architecture; - unsigned int _memory; - - string _cpu_model; - unsigned int _cpu_cores; - - protected: - Platform() {} - virtual~ Platform() {} - - void setUUID(const string uuid) { _uuid = uuid; } - void setHostname(const string hostname) { _hostname = hostname; } - void setHypervisor(const string hypervisor) { _hypervisor = hypervisor; } - void setArchitecture(const string arch) { _architecture = arch; } - void setMemory(unsigned int memory) { _memory = memory; } - - void setCPUModel(const string model) { _cpu_model = model; } - void setNumberOfCPUCores(const int cores) { _cpu_cores = cores; } - - public: - // the singleton instance - static Platform* instance(); - - string getUUID() const { return _uuid; } - string getHostname() const { return _hostname; } - string getHypervisor() const { return _hypervisor; } - string getArchitecture() const { return _architecture; } - unsigned int getMemory() const { return _memory; } - - string getCPUModel() const { return _cpu_model; } - unsigned int getNumberOfCPUCores() const { return _cpu_cores; } - - virtual double getLoadAverage() const = 0; -}; - -#endif diff --git a/src/qmf/hostagent.cpp b/src/qmf/hostagent.cpp index 94004d5..0e9a2a3 100644 --- a/src/qmf/hostagent.cpp +++ b/src/qmf/hostagent.cpp @@ -24,13 +24,10 @@ #include "qmf/com/redhat/matahari/EventHeartbeat.h"
HostAgent::HostAgent() -{ - host_register_listener(this); -} +{}
HostAgent::~HostAgent() -{ -} +{}
void HostAgent::setup(ManagementAgent* agent) diff --git a/src/qmf/hostagent.h b/src/qmf/hostagent.h index 7f7bbaa..6744400 100644 --- a/src/qmf/hostagent.h +++ b/src/qmf/hostagent.h @@ -24,7 +24,6 @@ #include <string>
#include "host.h" -#include "hostlistener.h"
#include "qmf/com/redhat/matahari/Host.h"
@@ -33,7 +32,7 @@ using namespace std;
namespace _qmf = qmf::com::redhat::matahari;
-class HostAgent : public Manageable, public HostListener +class HostAgent : public Manageable { private: _qmf::Host* _management_object; diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 13fea3d..61f142d 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -1,33 +1,29 @@ - bin_PROGRAMS = \ - testhostapis \ + testdatahandler \ testmultiplexer
INCLUDES = \ -I$(top_builddir)/lib \ -I$(top_srcdir)/lib \ - -I$(top_srcdir)/src + -I$(top_srcdir)/src \ + -I/usr/include/libxml2 + +testdatahandler_SOURCES =\ + $(top_srcdir)/src/virtio/datahandler.c \ + $(top_srcdir)/src/virtio/datahandler.h \ + $(top_srcdir)/src/virtio/lib_crc.c \ + $(top_srcdir)/src/virtio/lib_crc.h \ + $(top_srcdir)/src/virtio/multiplexer.c \ + $(top_srcdir)/src/virtio/multiplexer.h \ + testdatahandler.c
+testdatahandler_LDADD = -lcheck -lxml2 +testdatahandler_LDADD += ../../lib/libmatahari.a
testmultiplexer_SOURCES = \ - $(top_srcdir)/src/virtio/multiplexer.cpp \ + $(top_srcdir)/src/virtio/multiplexer.c \ $(top_srcdir)/src/virtio/multiplexer.h \ - testmultiplexer.cpp \ - testmultiplexer.h + testmultiplexer.c
testmultiplexer_LDADD = -lcppunit -testmultiplexer_LDADD += ../../lib/libgnu.a - -testhostapis_SOURCES = \ - $(top_srcdir)/src/host.cpp \ - $(top_srcdir)/src/host.h \ - $(top_srcdir)/src/linux_platform.cpp \ - $(top_srcdir)/src/linux_platform.h \ - $(top_srcdir)/src/platform.cpp \ - $(top_srcdir)/src/platform.h \ - testhostapis.cpp \ - testhostapis.h - -testhostapis_LDFLAGS = -L/usr/local/lib -testhostapis_LDADD = -lcppunit $(LIBVIRT_LIBS) $(PCRE_LIBS) $(UDEV_LIBS) -testhostapis_LDADD += ../../lib/libmatahari.a +testmultiplexer_LDADD += ../../lib/libmatahari.a diff --git a/src/tests/testdatahandler.c b/src/tests/testdatahandler.c new file mode 100644 index 0000000..09dfdb7 --- /dev/null +++ b/src/tests/testdatahandler.c @@ -0,0 +1,255 @@ +/* testdatahandler.c - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include <check.h> +#include <libxml/parser.h> +#include <libxml/xpath.h> +#include <stdlib.h> +#include <string.h> + +#include "virtio/datahandler.h" + +t_datahandler_payload payload; + +#define REPLACE_REQUEST(payload, content) {\ + payload.request_payload = content;\ + payload.request_length = strlen(content);\ + payload.request_crc = datahandler_calculate_crc(content, strlen(content)); \ + } + +#define APINAME "testapi" + +void +setup(void) +{ + payload.request_payload = "\ + <matahari type="request" api="testapi">\n\ + <args>\n\ + <arg name="foo">bar</arg>\n\ + </args>\n\ + </matahari>"; + payload.request_length = strlen(payload.request_payload); + payload.request_crc = + datahandler_calculate_crc(payload.request_payload, + payload.request_length); +} + +void +teardown(void) +{} + +START_TEST (test_validate_crc) +{ + char* value = "123456789"; + unsigned int length = strlen(value); + + fail_unless (datahandler_calculate_crc(value, length) == 3421780262L, + "The returned CRC value was invalid."); +} +END_TEST + +int +check_response(t_datahandler_payload payload, char* expression) +{ + int result = -1; + + xmlDocPtr document = xmlParseMemory(payload.response_payload, + payload.response_length); + if(document) + { + xmlXPathContextPtr context = xmlXPathNewContext(document); + + if(context) + { + xmlXPathObjectPtr xpathobj = + xmlXPathEvalExpression(BAD_CAST expression, context); + + if(xpathobj && ! xmlXPathNodeSetIsEmpty(xpathobj->nodesetval)) + { + result = 0; + } + + if(xpathobj) xmlXPathFreeObject(xpathobj); + xmlXPathFreeContext(context); + } + xmlFreeDoc(document); + } + + return result; +} + +START_TEST (test_process_with_null_data) +{ + fail_unless (datahandler_process_payload(NULL) == -1, + "Call should have returned an error."); +} +END_TEST + +START_TEST (test_process_with_empty_data) +{ + REPLACE_REQUEST(payload, ""); + + fail_unless (!datahandler_process_payload(&payload), + "Call should not have failed."); + fail_unless (!check_response(payload, "/matahari[@type='failure']"), + "The response should have indicated a failure."); +} +END_TEST + +START_TEST (test_process_with_invalid_crc) +{ + payload.request_crc++; + + fail_unless (!datahandler_process_payload(&payload), + "Called should not have failed."); + fail_unless (!check_response(payload, "/matahari[@type='failure']"), + "The response should have indicated failure."); +} +END_TEST + +#define REQUEST_SHOULD_NOT_HAVE_FAILED(payload) {\ + fail_unless (!datahandler_process_payload(&payload),\ + "Calls hould not have failed.");\ + } + +#define RESPONSE_MUST_BE_A_FAILURE(payload) {\ + fail_unless (!check_response(payload, "/matahari[@type='failure']"),\ + "The response should have indicated a failure.");\ + } +START_TEST (test_process_with_invalid_xml) +{ + REPLACE_REQUEST(payload, "<farkle>"); + + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + RESPONSE_MUST_BE_A_FAILURE(payload); +} +END_TEST + +START_TEST (test_process_request_check_root) +{ + REPLACE_REQUEST(payload, "<matahatrack />"); + + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + RESPONSE_MUST_BE_A_FAILURE(payload); +} +END_TEST + +START_TEST (test_process_request_without_type) +{ + REPLACE_REQUEST(payload, "<matahari />"); + + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + RESPONSE_MUST_BE_A_FAILURE(payload); +} +END_TEST + +START_TEST (test_process_request_check_type) +{ + REPLACE_REQUEST(payload, "<matahari type="response" api="foo" />"); + + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + RESPONSE_MUST_BE_A_FAILURE(payload); +} +END_TEST + +START_TEST (test_process_request_without_api) +{ + REPLACE_REQUEST(payload, "<matahari type="request" />"); + + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + RESPONSE_MUST_BE_A_FAILURE(payload); +} +END_TEST + +START_TEST (test_process_request_without_args) +{ + REPLACE_REQUEST(payload, "<matahari type="request" api="test">\ + </matahari>"); + + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + RESPONSE_MUST_BE_A_FAILURE(payload); +} +END_TEST + +const char* +test_request_calls_api_callback(const char* payload) +{ + return "\ + <response name="foo">\ + <element>\ + <value name="bar">Yo!</value>\ + </element>\ + </response>"; +} + +START_TEST (test_process_request_with_bad_api) +{ + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + RESPONSE_MUST_BE_A_FAILURE(payload); +} +END_TEST + +START_TEST (test_process_request_calls_api) +{ + multiplexer_register_api(APINAME, test_request_calls_api_callback); + + REQUEST_SHOULD_NOT_HAVE_FAILED(payload); + fail_unless (!check_response(payload, "/matahari[@type='response']"), + "Response should have been of type 'response'."); +} +END_TEST + +Suite* +datahandler_test_suite(void) +{ + Suite* result = suite_create("CRC"); + + TCase* tc_process = tcase_create("Process"); + tcase_add_checked_fixture(tc_process, setup, teardown); + tcase_add_test(tc_process, test_validate_crc); + tcase_add_test(tc_process, test_process_with_null_data); + tcase_add_test(tc_process, test_process_with_empty_data); + tcase_add_test(tc_process, test_process_with_invalid_crc); + tcase_add_test(tc_process, test_process_with_invalid_xml); + tcase_add_test(tc_process, test_process_request_check_root); + tcase_add_test(tc_process, test_process_request_without_type); + tcase_add_test(tc_process, test_process_request_check_type); + tcase_add_test(tc_process, test_process_request_without_api); + tcase_add_test(tc_process, test_process_request_without_args); + tcase_add_test(tc_process, test_process_request_with_bad_api); + tcase_add_test(tc_process, test_process_request_calls_api); + suite_add_tcase(result, tc_process); + + return result; +} + +int +main(int argc, char** argv) +{ + int failures; + + Suite* suite = datahandler_test_suite(); + SRunner* srunner = srunner_create(suite); + + srunner_run_all(srunner, CK_NORMAL); + failures = srunner_ntests_failed(srunner); + srunner_free(srunner); + + return (failures == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/tests/testhostapis.h b/src/tests/testhostapis.h deleted file mode 100644 index faebb22..0000000 --- a/src/tests/testhostapis.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __TESTHOSTAPIS_H -#define __TESTHOSTAPIS_H - -/* testhostapis.h - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include <cppunit/TestCase.h> -#include <cppunit/TestSuite.h> - -#include "platform.h" - -using namespace CppUnit; - -class TestHostApis : public TestCase -{ - private: - Platform* platform; - - public: - TestHostApis(); - virtual ~TestHostApis(); - - static TestSuite* suite(); - - void setUp(); - - void testHostGetUUID(); - void testHostGetHostname(); - void testHostGetHypervisor(); - void testHostGetArchitecture(); - void testHostGetMemory(); - void testHostGetCpuModel(); - void testHostGetNumberOfCpuCores(); - void testHostGetLoadAverage(); - void testHostIsBeeping(); -}; - -#endif diff --git a/src/tests/testmultiplexer.c b/src/tests/testmultiplexer.c new file mode 100644 index 0000000..56395bf --- /dev/null +++ b/src/tests/testmultiplexer.c @@ -0,0 +1,179 @@ +/* testmultiplexer.c - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include <check.h> +#include <stdlib.h> + +#include "virtio/multiplexer.h" + +void +setup(void) +{} + +void +teardown(void) +{} + +#define APINAME "testapi" +#define CONTENT "<args />" + +const char* +test_callback(const char* input) +{ + return NULL; +} + +const char* +test_new_callback(const char* input) +{ + return NULL; +} + +START_TEST (test_register_with_null_name) +{ + fail_unless (multiplexer_register_api(NULL, NULL) == -1, + "Registration should not have succeeded"); +} +END_TEST + +START_TEST (test_register_with_empty_name) +{ + fail_unless (multiplexer_register_api("", NULL) == -1, + "Registration should not have succeeded."); +} +END_TEST + +START_TEST (test_register_will_null_function) +{ + fail_unless (multiplexer_register_api(APINAME, NULL) == -1, + "Registration should not have succeeded"); +} +END_TEST + +START_TEST (test_register_succeeds) +{ + fail_unless (!multiplexer_register_api(APINAME, test_callback), + "Registration should have succeeded."); + fail_unless (multiplexer_get_api_function(APINAME) == test_callback, + "The method was not actually registered."); +} +END_TEST + +START_TEST (test_register_with_existing_api_name) +{ + fail_unless (!multiplexer_register_api(APINAME, test_callback), + "Registration should have succeeded."); + fail_unless (!multiplexer_register_api(APINAME, test_new_callback), + "Registration should have succeeded."); + fail_unless (multiplexer_get_api_function(APINAME) == test_new_callback, + "The original API should have been replaced."); +} +END_TEST + +START_TEST (test_unregistered_api_returns_null) +{ + fail_if (multiplexer_get_api_function(APINAME), + "No callback should have been returned."); +} +END_TEST + +START_TEST (test_invoke_with_null_apiname) +{ + fail_unless (multiplexer_invoke_api(NULL, CONTENT) == NULL, + "The API call should have failed."); +} +END_TEST + +START_TEST (test_invoke_with_empty_apiname) +{ + fail_unless (multiplexer_invoke_api("", CONTENT) == NULL, + "The API call should have faile"); +} +END_TEST + +START_TEST (test_invoke_unregistered_api) +{ + fail_unless (multiplexer_invoke_api("farkle", CONTENT) == NULL, + "The API call should have failed."); +} +END_TEST + +START_TEST (test_invoke_with_no_content) +{ + fail_unless (multiplexer_invoke_api(APINAME, NULL) == NULL, + "The API call should have failed."); +} +END_TEST + +const char* +test_invoke_callback(const char* input) +{ + return input; +} + +START_TEST (test_invoke_succeeds) +{ + multiplexer_register_api(APINAME, test_invoke_callback); + + const char* result = multiplexer_invoke_api(APINAME, CONTENT); + + fail_if (!result, "The API call should have succeeded."); + fail_unless (!strcmp(CONTENT, result), "The call returned the wrong value."); +} +END_TEST + +Suite* +multiplexer_test_suite(void) +{ + Suite* result = suite_create("Multiplexer"); + + TCase* tc_register = tcase_create("Register"); + tcase_add_checked_fixture(tc_register, setup, teardown); + tcase_add_test(tc_register, test_register_with_null_name); + tcase_add_test(tc_register, test_register_with_empty_name); + tcase_add_test(tc_register, test_register_will_null_function); + tcase_add_test(tc_register, test_register_succeeds); + tcase_add_test(tc_register, test_register_with_existing_api_name); + tcase_add_test(tc_register, test_unregistered_api_returns_null); + suite_add_tcase(result, tc_register); + + TCase* tc_invoke = tcase_create("Invoke"); + tcase_add_checked_fixture(tc_invoke, setup, teardown); + tcase_add_test(tc_invoke, test_invoke_with_null_apiname); + tcase_add_test(tc_invoke, test_invoke_unregistered_api); + tcase_add_test(tc_invoke, test_invoke_with_no_content); + tcase_add_test(tc_invoke, test_invoke_succeeds); + suite_add_tcase(result, tc_invoke); + return result; +} + +int +main(int argc, char** argv) +{ + int failures; + + Suite* suite = multiplexer_test_suite(); + SRunner* srunner = srunner_create(suite); + + srunner_run_all(srunner, CK_NORMAL); + failures = srunner_ntests_failed(srunner); + srunner_free(srunner); + + return (failures == 0) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/src/tests/testmultiplexer.cpp b/src/tests/testmultiplexer.cpp deleted file mode 100644 index 6208cc2..0000000 --- a/src/tests/testmultiplexer.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* testmultiplexer.cpp - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include <config.h> -#include "testmultiplexer.h" - -#include "virtio/multiplexer.h" - -#include <cppunit/TestAssert.h> -#include <cppunit/TestCaller.h> -#include <cppunit/TestResult.h> -#include <cppunit/TestSuite.h> -#include <cppunit/ui/text/TestRunner.h> - -const string APINAME("testapifunction"); - -const char* -test_callback_function(const char* input) -{ - return input; -} - -TestMultiplexer::TestMultiplexer() - :TestCase("TestMultiplexer") -{} - -TestSuite* -TestMultiplexer::suite() -{ - CppUnit::TestSuite *result = new CppUnit::TestSuite("TestMultiplexer"); - - result->addTest(new CppUnit::TestCaller<TestMultiplexer> - ("testBadAPINameGetsNull", - &TestMultiplexer::testUnregisteredAPIIsNull)); - result->addTest(new CppUnit::TestCaller<TestMultiplexer> - ("testRegisterAPIMethod", - &TestMultiplexer::testRegisterAPIMethod)); - result->addTest(new CppUnit::TestCaller<TestMultiplexer> - ("testEnsureCallingAnUnregisteredAPIFails", - &TestMultiplexer::testEnsureCallingAnUnregisteredAPIFails)); - result->addTest(new CppUnit::TestCaller<TestMultiplexer> - ("testEnsureAPIIsCalled", - &TestMultiplexer::testEnsureAPIIsCalled)); - - return result; -} - -void -TestMultiplexer::setUp() -{ - Multiplexer::instance()->registerAPI(APINAME, test_callback_function); -} - -void -TestMultiplexer::testUnregisteredAPIIsNull() -{ - CPPUNIT_ASSERT(NULL == Multiplexer::instance()->getAPI(APINAME + "!")); -} - -void -TestMultiplexer::testRegisterAPIMethod() -{ - t_apifunction apifunction = test_callback_function; - - CPPUNIT_ASSERT(apifunction == Multiplexer::instance()->getAPI(APINAME)); -} - -void -TestMultiplexer::testEnsureCallingAnUnregisteredAPIFails() -{ - string input = string("This is some input"); - string result = Multiplexer::instance()->invokeAPI(APINAME + "!", input); - - CPPUNIT_ASSERT(string("") == result); -} - -void TestMultiplexer::testEnsureAPIIsCalled() -{ - string expected = "This is what I expected"; - string result = Multiplexer::instance()->invokeAPI(APINAME, expected); - - CPPUNIT_ASSERT(expected == result); -} - -int -main(int argc, char** argv) -{ - CppUnit::TextUi::TestRunner runner; - - runner.addTest(TestMultiplexer::suite()); - runner.run(); - - return 0; -} diff --git a/src/tests/testmultiplexer.h b/src/tests/testmultiplexer.h deleted file mode 100644 index 04cb9e5..0000000 --- a/src/tests/testmultiplexer.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef __TESTMULTIPLEXER_H -#define __TESTMULTIPLEXER_H - -/* testmultiplexer.h - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include "virtio/multiplexer.h" - -#include <cppunit/TestCase.h> -#include <cppunit/TestSuite.h> - -using namespace CppUnit; -using namespace std; - -class TestMultiplexer : public CppUnit::TestCase -{ - public: - TestMultiplexer(); - - static TestSuite* suite(); - - void setUp(); - - void testUnregisteredAPIIsNull(); - void testRegisterAPIMethod(); - void testEnsureCallingAnUnregisteredAPIFails(); - void testEnsureAPIIsCalled(); -}; - -#endif diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..733d309 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,64 @@ +/* utils.c - Copyright (C) 2009 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include <config.h> +#include <pcre.h> +#include <stdio.h> +#include <string.h> +#include "utils.h" + +void search_file(const char* filename, const char* expression, + search_callback_t callback) +{ + const char* pattern; + const char* errors; + int erroffset; + pcre *expr; + char line[512]; + + pattern = expression; + + if (expr = pcre_compile(pattern, 0, &errors, &erroffset, NULL)) + { + FILE* input; + + if( (input = fopen(filename, "r")) != NULL) + { + while (! feof(input)) + { + fgets(line, sizeof line, input); + + size_t len = strcspn(line, "\n"); + int matches[9]; + int offset = 0; + int flags = 0; + line[len] = '\0'; + bool done = false; + + while (0 < pcre_exec(expr, 0, line, len, + offset, flags, matches, 9) && !done) + { + done = callback(line, offset, matches); + flags |= PCRE_NOTBOL; + } + } + } + fclose(input); + } +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..a003383 --- /dev/null +++ b/src/utils.h @@ -0,0 +1,37 @@ +#ifndef __UTILS_H +#define __UTILS_H + +/* utils.h - Copyright (C) 2009 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include <config.h> +#include <stdbool.h> + +typedef bool(*search_callback_t)(char*, int, int*); + +/* Performs a regular expression search through specified file + using the provided regular expression. + + For each result discovered, the supplied callback method + is invoked. +*/ +void search_file(const char* filename, const char* expression, + search_callback_t callback); + +#endif diff --git a/src/virtio/datahandler.c b/src/virtio/datahandler.c new file mode 100644 index 0000000..3bf363c --- /dev/null +++ b/src/virtio/datahandler.c @@ -0,0 +1,268 @@ +/* datahandler.cpp - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include "virtio/datahandler.h" + +#include <libxml/tree.h> +#include <libxml/xpath.h> +#include <libxml/xpointer.h> +#include "virtio/multiplexer.h" +#include <string.h> +#include "virtio/lib_crc.h" + +void +_extract_api_and_make_call(t_datahandler_payload* payload, xmlDocPtr request); + +char* +_create_error_content(const char* message) +{ + char* result = malloc(1000); + + sprintf(result, "\ + <response name="error">\ + <element>\ + <value name="message">%s</value>\ + </element>\ + </response>", message); + + return result; +} + +void +_create_document_with_content(t_datahandler_payload* payload, + char* type, + const char* response, + unsigned int length) +{ + xmlDocPtr content = xmlNewDoc(BAD_CAST "1.0"); + xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "matahari"); + xmlNodePtr responses = xmlNewNode(NULL, BAD_CAST "responses"); + + xmlNewProp(root, BAD_CAST "type",BAD_CAST type); + xmlDocSetRootElement(content, root); + xmlAddChild(root, responses); + + // parse the content + xmlDocPtr contentnode = xmlParseMemory(response, length); + + xmlAddChild(responses, contentnode->children); + + // set the payload response, crc and length + xmlChar* buffertext; + int buffersize; + + xmlDocDumpFormatMemory(content, &buffertext, &buffersize, 1); + payload->response_payload = (char*) buffertext; + payload->response_length = buffersize; + payload->response_crc = + datahandler_calculate_crc(payload->response_payload, + payload->response_length); +} + +void +_prepare_request_payload(t_datahandler_payload* payload, const char* message, + t_matahari_message_type response_type) +{ + payload->response_type = response_type; + + if(response_type == FAILURE) + { + char* response_message = _create_error_content(message); + _create_document_with_content(payload, "failure", + response_message, strlen(response_message)); + free(response_message); + } + else + { + _create_document_with_content(payload, "response", + message, strlen(message)); + } +} + +void +_request_failure(t_datahandler_payload* payload, const char* message) +{ + _prepare_request_payload(payload, message, FAILURE); +} + +void +_request_success(t_datahandler_payload* payload, const char* message) +{ + _prepare_request_payload(payload, message, RESPONSE); +} + +int +datahandler_process_payload(t_datahandler_payload* payload) +{ + int result = -1; + + if(payload) + { + result = 0; + + if(payload->request_length > 0) + { + // setup the response fields + payload->response_payload = 0; + payload->response_length = 0; + payload->response_crc = 0L; + + unsigned long crc = + datahandler_calculate_crc(payload->request_payload, + payload->request_length); + + if(crc == payload->request_crc) + { + xmlDocPtr request = xmlParseMemory(payload->request_payload, + payload->request_length); + xmlErrorPtr error = xmlGetLastError(); + + if(request != NULL && !error) + { + _extract_api_and_make_call(payload, request); + } + else + { + _request_failure(payload, "No request document found."); + } + + if(request) xmlFreeDoc(request); + } + else + { + _request_failure(payload, "Request fails CRC check."); + } + } + else + { + _request_failure(payload, "No request payload present."); + } + } + + return result; +} + +unsigned long +datahandler_calculate_crc(char* data, unsigned int length) +{ + unsigned long result = 0xffffffffL; + char* current = (char *)data; + unsigned int count = 0; + + while(count < length) + { + result = update_crc_32(result, *current); + current++; + count++; + } + + result ^= 0xffffffffL; + + return result; +} + +#define FREE_XPATH_OBJECT(pathobj) {\ + if(pathobj) xmlXPathFreeObject(pathobj);\ + pathobj = NULL;\ + } + +void +_extract_api_and_make_call(t_datahandler_payload* payload, xmlDocPtr request) +{ + xmlXPathContextPtr context = xmlXPathNewContext(request); + xmlXPathObjectPtr pathobj = + xmlXPathEvalExpression(BAD_CAST "/matahari/@type", context); + + if(pathobj && !xmlXPathNodeSetIsEmpty(pathobj->nodesetval)) + { + char* type = xmlXPathCastToString(pathobj); + + if(!strncmp(type, "request", strlen("request"))) + { + FREE_XPATH_OBJECT(pathobj); + + pathobj = xmlXPathEvalExpression(BAD_CAST "/matahari/@api", context); + + if(pathobj && !xmlXPathNodeSetIsEmpty(pathobj->nodesetval)) + { + char* api = xmlXPathCastToString(pathobj); + FREE_XPATH_OBJECT(pathobj); + + t_apifunction apifunction = multiplexer_get_api_function(api); + + if(apifunction) + { + pathobj = xmlXPathEvalExpression(BAD_CAST "/matahari/args", + context); + if(pathobj && !xmlXPathNodeSetIsEmpty(pathobj->nodesetval)) + { + xmlDocPtr args = xmlNewDoc(NULL); + xmlNodePtr argroot = xmlXPtrBuildNodeList(pathobj); + + xmlDocSetRootElement(args, argroot); + + xmlChar* contenttext; + int contentsize; + + xmlDocDumpFormatMemory(args, + &contenttext, &contentsize, 1); + + const char* response = apifunction(contenttext); + _request_success(payload, response); + + free(contenttext); + if(args) xmlFreeDoc(args); + } + else + { + _request_failure(payload, + "Request did not contain arguments."); + } + } + else + { + _request_failure(payload, "Invalid API specified."); + } + + free(api); + FREE_XPATH_OBJECT(pathobj); + } + else + { + _request_failure(payload, "Request did not specify an API."); + } + + FREE_XPATH_OBJECT(pathobj); + } + else + { + _request_failure(payload, "Request was not of type 'request'."); + } + + if(type) free(type); + + FREE_XPATH_OBJECT(pathobj); + } + else + { + _request_failure(payload, "No API was specified."); + } + + xmlXPathFreeContext(context); +} diff --git a/src/virtio/datahandler.h b/src/virtio/datahandler.h new file mode 100644 index 0000000..4323280 --- /dev/null +++ b/src/virtio/datahandler.h @@ -0,0 +1,61 @@ +#ifndef __DATAHANDLER_H +#define __DATAHANDLER_H + +/* datahandler.h - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum {REQUEST, RESPONSE, FAILURE} t_matahari_message_type; + +/* A t_datahandler_payload struct holds the request payload + received from a remote system. After processing, it will + also hold the response payload and details. +*/ +typedef struct +{ + char* request_id; + unsigned long request_crc; + char* request_payload; + unsigned int request_length; + t_matahari_message_type response_type; + unsigned long response_crc; + char* response_payload; + unsigned long response_length; +} t_datahandler_payload; + +/* A function thatprocesses data received from a remote + source extracts and validates the actual request + within the payload. + + It takes as argument a struct holding the request details, + and will attach the response details on completion. +*/ +int datahandler_process_payload(t_datahandler_payload* payload); + +/* Calculates a CRC value for the supplied data. */ +unsigned long datahandler_calculate_crc(char* data, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/virtio/lib_crc.c b/src/virtio/lib_crc.c new file mode 100644 index 0000000..26b6b99 --- /dev/null +++ b/src/virtio/lib_crc.c @@ -0,0 +1,459 @@ +#include "lib_crc.h" + + + + /*******************************************************************\ + * * + * Library : lib_crc * + * File : lib_crc.c * + * Author : Lammert Bies 1999-2008 * + * E-mail : info@lammertbies.nl * + * Language : ANSI C * + * * + * * + * Description * + * =========== * + * * + * The file lib_crc.c contains the private and public func- * + * tions used for the calculation of CRC-16, CRC-CCITT and * + * CRC-32 cyclic redundancy values. * + * * + * * + * Dependencies * + * ============ * + * * + * lib_crc.h CRC definitions and prototypes * + * * + * * + * Modification history * + * ==================== * + * * + * Date Version Comment * + * * + * 2008-04-20 1.16 Added CRC-CCITT calculation for Kermit * + * * + * 2007-04-01 1.15 Added CRC16 calculation for Modbus * + * * + * 2007-03-28 1.14 Added CRC16 routine for Sick devices * + * * + * 2005-12-17 1.13 Added CRC-CCITT with initial 0x1D0F * + * * + * 2005-05-14 1.12 Added CRC-CCITT with start value 0 * + * * + * 2005-02-05 1.11 Fixed bug in CRC-DNP routine * + * * + * 2005-02-04 1.10 Added CRC-DNP routines * + * * + * 1999-02-21 1.01 Added FALSE and TRUE mnemonics * + * * + * 1999-01-22 1.00 Initial source * + * * + *******************************************************************/ + + + + /*******************************************************************\ + * * + * #define P_xxxx * + * * + * The CRC's are computed using polynomials. The coefficients * + * for the algorithms are defined by the following constants. * + * * + *******************************************************************/ + +#define P_16 0xA001 +#define P_32 0xEDB88320L +#define P_CCITT 0x1021 +#define P_DNP 0xA6BC +#define P_KERMIT 0x8408 +#define P_SICK 0x8005 + + + + /*******************************************************************\ + * * + * static int crc_tab...init * + * static unsigned ... crc_tab...[] * + * * + * The algorithms use tables with precalculated values. This * + * speeds up the calculation dramaticaly. The first time the * + * CRC function is called, the table for that specific calcu- * + * lation is set up. The ...init variables are used to deter- * + * mine if the initialization has taken place. The calculated * + * values are stored in the crc_tab... arrays. * + * * + * The variables are declared static. This makes them invisi- * + * ble for other modules of the program. * + * * + *******************************************************************/ + +static int crc_tab16_init = FALSE; +static int crc_tab32_init = FALSE; +static int crc_tabccitt_init = FALSE; +static int crc_tabdnp_init = FALSE; +static int crc_tabkermit_init = FALSE; + +static unsigned short crc_tab16[256]; +static unsigned long crc_tab32[256]; +static unsigned short crc_tabccitt[256]; +static unsigned short crc_tabdnp[256]; +static unsigned short crc_tabkermit[256]; + + + + /*******************************************************************\ + * * + * static void init_crc...tab(); * + * * + * Three local functions are used to initialize the tables * + * with values for the algorithm. * + * * + *******************************************************************/ + +static void init_crc16_tab( void ); +static void init_crc32_tab( void ); +static void init_crcccitt_tab( void ); +static void init_crcdnp_tab( void ); +static void init_crckermit_tab( void ); + + + + /*******************************************************************\ + * * + * unsigned short update_crc_ccitt( unsigned long crc, char c ); * + * * + * The function update_crc_ccitt calculates a new CRC-CCITT * + * value based on the previous value of the CRC and the next * + * byte of the data to be checked. * + * * + *******************************************************************/ + +unsigned short update_crc_ccitt( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tabccitt_init ) init_crcccitt_tab(); + + tmp = (crc >> 8) ^ short_c; + crc = (crc << 8) ^ crc_tabccitt[tmp]; + + return crc; + +} /* update_crc_ccitt */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_sick( * + * unsigned long crc, char c, char prev_byte ); * + * * + * The function update_crc_sick calculates a new CRC-SICK * + * value based on the previous value of the CRC and the next * + * byte of the data to be checked. * + * * + *******************************************************************/ + +unsigned short update_crc_sick( unsigned short crc, char c, char prev_byte ) { + + unsigned short short_c, short_p; + + short_c = 0x00ff & (unsigned short) c; + short_p = ( 0x00ff & (unsigned short) prev_byte ) << 8; + + if ( crc & 0x8000 ) crc = ( crc << 1 ) ^ P_SICK; + else crc = crc << 1; + + crc &= 0xffff; + crc ^= ( short_c | short_p ); + + return crc; + +} /* update_crc_sick */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_16( unsigned short crc, char c ); * + * * + * The function update_crc_16 calculates a new CRC-16 value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + *******************************************************************/ + +unsigned short update_crc_16( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tab16_init ) init_crc16_tab(); + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crc_tab16[ tmp & 0xff ]; + + return crc; + +} /* update_crc_16 */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_kermit( unsigned short crc, char c ); * + * * + * The function update_crc_kermit calculates a new CRC value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + *******************************************************************/ + +unsigned short update_crc_kermit( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tabkermit_init ) init_crckermit_tab(); + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crc_tabkermit[ tmp & 0xff ]; + + return crc; + +} /* update_crc_kermit */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_dnp( unsigned short crc, char c ); * + * * + * The function update_crc_dnp calculates a new CRC-DNP value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + *******************************************************************/ + +unsigned short update_crc_dnp( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tabdnp_init ) init_crcdnp_tab(); + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crc_tabdnp[ tmp & 0xff ]; + + return crc; + +} /* update_crc_dnp */ + + + + /*******************************************************************\ + * * + * unsigned long update_crc_32( unsigned long crc, char c ); * + * * + * The function update_crc_32 calculates a new CRC-32 value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + *******************************************************************/ + +unsigned long update_crc_32( unsigned long crc, char c ) { + + unsigned long tmp, long_c; + + long_c = 0x000000ffL & (unsigned long) c; + + if ( ! crc_tab32_init ) init_crc32_tab(); + + tmp = crc ^ long_c; + crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ]; + + return crc; + +} /* update_crc_32 */ + + + + /*******************************************************************\ + * * + * static void init_crc16_tab( void ); * + * * + * The function init_crc16_tab() is used to fill the array * + * for calculation of the CRC-16 with values. * + * * + *******************************************************************/ + +static void init_crc16_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_16; + else crc = crc >> 1; + + c = c >> 1; + } + + crc_tab16[i] = crc; + } + + crc_tab16_init = TRUE; + +} /* init_crc16_tab */ + + + + /*******************************************************************\ + * * + * static void init_crckermit_tab( void ); * + * * + * The function init_crckermit_tab() is used to fill the array * + * for calculation of the CRC Kermit with values. * + * * + *******************************************************************/ + +static void init_crckermit_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_KERMIT; + else crc = crc >> 1; + + c = c >> 1; + } + + crc_tabkermit[i] = crc; + } + + crc_tabkermit_init = TRUE; + +} /* init_crckermit_tab */ + + + + /*******************************************************************\ + * * + * static void init_crcdnp_tab( void ); * + * * + * The function init_crcdnp_tab() is used to fill the array * + * for calculation of the CRC-DNP with values. * + * * + *******************************************************************/ + +static void init_crcdnp_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_DNP; + else crc = crc >> 1; + + c = c >> 1; + } + + crc_tabdnp[i] = crc; + } + + crc_tabdnp_init = TRUE; + +} /* init_crcdnp_tab */ + + + + /*******************************************************************\ + * * + * static void init_crc32_tab( void ); * + * * + * The function init_crc32_tab() is used to fill the array * + * for calculation of the CRC-32 with values. * + * * + *******************************************************************/ + +static void init_crc32_tab( void ) { + + int i, j; + unsigned long crc; + + for (i=0; i<256; i++) { + + crc = (unsigned long) i; + + for (j=0; j<8; j++) { + + if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ P_32; + else crc = crc >> 1; + } + + crc_tab32[i] = crc; + } + + crc_tab32_init = TRUE; + +} /* init_crc32_tab */ + + + + /*******************************************************************\ + * * + * static void init_crcccitt_tab( void ); * + * * + * The function init_crcccitt_tab() is used to fill the array * + * for calculation of the CRC-CCITT with values. * + * * + *******************************************************************/ + +static void init_crcccitt_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = ((unsigned short) i) << 8; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ P_CCITT; + else crc = crc << 1; + + c = c << 1; + } + + crc_tabccitt[i] = crc; + } + + crc_tabccitt_init = TRUE; + +} /* init_crcccitt_tab */ diff --git a/src/virtio/lib_crc.h b/src/virtio/lib_crc.h new file mode 100644 index 0000000..ea5ca76 --- /dev/null +++ b/src/virtio/lib_crc.h @@ -0,0 +1,66 @@ + /*******************************************************************\ + * * + * Library : lib_crc * + * File : lib_crc.h * + * Author : Lammert Bies 1999-2008 * + * E-mail : info@lammertbies.nl * + * Language : ANSI C * + * * + * * + * Description * + * =========== * + * * + * The file lib_crc.h contains public definitions and proto- * + * types for the CRC functions present in lib_crc.c. * + * * + * * + * Dependencies * + * ============ * + * * + * none * + * * + * * + * Modification history * + * ==================== * + * * + * Date Version Comment * + * * + * 2008-04-20 1.16 Added CRC-CCITT routine for Kermit * + * * + * 2007-04-01 1.15 Added CRC16 calculation for Modbus * + * * + * 2007-03-28 1.14 Added CRC16 routine for Sick devices * + * * + * 2005-12-17 1.13 Added CRC-CCITT with initial 0x1D0F * + * * + * 2005-02-14 1.12 Added CRC-CCITT with initial 0x0000 * + * * + * 2005-02-05 1.11 Fixed bug in CRC-DNP routine * + * * + * 2005-02-04 1.10 Added CRC-DNP routines * + * * + * 2005-01-07 1.02 Changes in tst_crc.c * + * * + * 1999-02-21 1.01 Added FALSE and TRUE mnemonics * + * * + * 1999-01-22 1.00 Initial source * + * * + *******************************************************************/ + + + +#define CRC_VERSION "1.16" + + + +#define FALSE 0 +#define TRUE 1 + + + +unsigned short update_crc_16( unsigned short crc, char c ); +unsigned long update_crc_32( unsigned long crc, char c ); +unsigned short update_crc_ccitt( unsigned short crc, char c ); +unsigned short update_crc_dnp( unsigned short crc, char c ); +unsigned short update_crc_kermit( unsigned short crc, char c ); +unsigned short update_crc_sick( unsigned short crc, char c, char prev_byte ); diff --git a/src/virtio/multiplexer.c b/src/virtio/multiplexer.c new file mode 100644 index 0000000..677e24c --- /dev/null +++ b/src/virtio/multiplexer.c @@ -0,0 +1,122 @@ +/* multiplexer.c - Copyright (C) 2010 Red Hat, Inc. + * Written by Darryl L. Pierce dpierce@redhat.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. A copy of the GNU General Public License is + * also available at http://www.gnu.org/copyleft/gpl.html. + */ + +#include "multiplexer.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define APINAMELENGTH 255 + +typedef struct _apifunction_list +{ + char apiname[APINAMELENGTH]; + t_apifunction callback; + struct _apifunction_list* next; +} t_apifunction_list; + +t_apifunction_list* _callbacks = NULL; + +int +multiplexer_register_api(const char* apiname, t_apifunction callback) +{ + int result = -1; + + if(apiname && strlen(apiname) && callback) + { + t_apifunction_list* newapi = NULL; + int existing = 0; + + /* first see if the api is already registered */ + newapi = _callbacks; + while(newapi && !existing) + { + if(!strcmp(newapi->apiname, apiname)) + { + existing = 1; + } + else + { + newapi = newapi->next; + } + } + + if(!newapi) + { + newapi = malloc(sizeof(t_apifunction_list)); + + strncpy(newapi->apiname, apiname, APINAMELENGTH); + newapi->callback = callback; + newapi->next = NULL; + + if(_callbacks) + { + t_apifunction_list* tail = NULL; + + while(tail->next) tail = tail->next; + tail->next = newapi; + } + else + { + _callbacks = newapi; + } + } + else + { + newapi->callback = callback; + } + + result = 0; + } + + return result; +} + +t_apifunction +multiplexer_get_api_function(const char* apiname) +{ + t_apifunction_list* current = _callbacks; + + while(current) + { + if(!strcmp(apiname, current->apiname)) + { + return current->callback; + } + current = current->next; + } + + return NULL; +} + +const char* +multiplexer_invoke_api(const char* apiname, const char* content) +{ + const char* result = NULL; + + t_apifunction api = multiplexer_get_api_function(apiname); + + if(api) + { + result = api(content); + } + + return result; +} diff --git a/src/virtio/multiplexer.cpp b/src/virtio/multiplexer.cpp deleted file mode 100644 index 8f72ddc..0000000 --- a/src/virtio/multiplexer.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* multiplexer.cpp - Copyright (C) 2010 Red Hat, Inc. - * Written by Darryl L. Pierce dpierce@redhat.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301, USA. A copy of the GNU General Public License is - * also available at http://www.gnu.org/copyleft/gpl.html. - */ - -#include <config.h> -#include "multiplexer.h" - -// the singleton -Multiplexer* Multiplexer::_instance = new Multiplexer(); - -typedef map<string, t_apifunction> APIMAP; - -Multiplexer::Multiplexer() -{} - -Multiplexer* -Multiplexer::instance() -{ - return _instance; -} - -void -Multiplexer::registerAPI(string name, t_apifunction apifunction) -{ - _apis.insert(APIMAP::value_type(string(name), apifunction)); -} - -t_apifunction -Multiplexer::getAPI(string name) -{ - return (*_apis.find(name)).second; -} - -string -Multiplexer::invokeAPI(string name, string input) -{ - string result = string(""); - t_apifunction funcptr = (*_apis.find(name)).second; - - if(funcptr) - { - result = funcptr(input.c_str()); - } - - return result; -} - diff --git a/src/virtio/multiplexer.h b/src/virtio/multiplexer.h index 26a288c..5d00adf 100644 --- a/src/virtio/multiplexer.h +++ b/src/virtio/multiplexer.h @@ -20,29 +20,35 @@ * also available at http://www.gnu.org/copyleft/gpl.html. */
-#include <map> -#include <string> - -using namespace std; - +/* Defines a function type that can be used as a callback + * for an API. + */ typedef const char*(*t_apifunction)(const char*);
-// Multiplexer processes the content received from a remote system. -class Multiplexer -{ - private: - Multiplexer(); - - static Multiplexer* _instance; - - map<string, t_apifunction> _apis; +/* Registers a new API that can be called back. + * + * INPUT: The name of the api. + * The callback function to be invoked. + * OUTPUT: 0 on success, -1 on failure. + */ +int +multiplexer_register_api(const char* name, t_apifunction callback);
- public: - static Multiplexer* instance(); +/* Returns a pointer to the callback registered for an API. + * + * INPUT: The name of the API. + * OUTPUT: A pointer to the function, or NULL if the API is not registered. + */ +t_apifunction +multiplexer_get_api_function(const char* name);
- void registerAPI(string apiname, t_apifunction apifunction); - t_apifunction getAPI(string apiname); - string invokeAPI(string apiname, string input); -}; +/* Invokes the named API, passing in the supplied argument. + * + * INPUT: The name of the API. + * The content to pass to the API. + * OUTPUT: The result of the API call, or NULL if the API call failed. + */ +const char* +multiplexer_invoke_api(const char* name, const char* content);
#endif