This patch brings together refactoring the datahandler, multiplexer and host APIs, as well as replacing all of the unit tests with Check tests.
With this, there are no other outstanding patches from me to be reviewed.
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
matahari@lists.fedorahosted.org