├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── cmake_uninstall.cmake.in ├── doxygen └── Doxyfile.in ├── files ├── commotiond.conf └── profiles.d │ └── example ├── openwrt ├── etc │ ├── config │ │ └── commotiond │ ├── init.d │ │ └── commotiond │ └── uci-defaults │ │ └── commotiond └── lib │ ├── functions │ └── commotion.sh │ └── netifd │ ├── commotion.dhcp.script │ └── proto │ └── commotion.sh ├── plugins ├── CMakeLists.txt ├── demo │ ├── CMakeLists.txt │ ├── README.md │ ├── demo.c │ └── demo.h ├── olsrd │ ├── olsrd.c │ └── olsrd.h └── serval-dna │ ├── CMakeLists.txt │ ├── README.md │ ├── commands.c │ ├── commands.h │ ├── crypto.c │ ├── crypto.h │ ├── keyring.c │ ├── keyring.h │ ├── olsr_mdp.c │ ├── olsr_mdp.h │ ├── sas_request.c │ ├── sas_request.h │ ├── serval-client.c │ ├── serval-config.h.in │ ├── serval-dna.c │ └── serval-dna.h ├── src ├── CMakeLists.txt ├── client.c ├── cmd.c ├── cmd.h ├── commotion.c ├── commotion.h ├── config.h.in ├── daemon.c ├── debug.h ├── extern │ ├── align.h │ ├── halloc.c │ ├── halloc.h │ ├── hlist.h │ ├── jsmn.c │ ├── jsmn.h │ ├── macros.h │ ├── md5.c │ ├── md5.h │ ├── wpa_ctrl.c │ └── wpa_ctrl.h ├── id.c ├── id.h ├── iface.c ├── iface.h ├── list.c ├── list.h ├── loop.c ├── loop.h ├── msg.c ├── msg.h ├── obj.c ├── obj.h ├── plugin.c ├── plugin.h ├── process.c ├── process.h ├── profile.c ├── profile.h ├── socket.c ├── socket.h ├── tree.c ├── tree.h ├── util.c └── util.h └── tests ├── CMakeLists.txt ├── list.cpp ├── loop.cpp ├── msg.cpp ├── profile.cpp ├── scheduler.cpp.old ├── socket.cpp ├── tree-next.cpp └── tree.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Libraries 5 | *.lib 6 | *.a 7 | 8 | # Shared objects (inc. Windows DLLs) 9 | *.dll 10 | *.so 11 | *.so.* 12 | *.dylib 13 | 14 | # Executables 15 | *.exe 16 | *.out 17 | *.app 18 | 19 | # CMake 20 | build 21 | config.h 22 | serval-config.h 23 | 24 | # Vim 25 | Session.vim 26 | 27 | # ctags 28 | tags 29 | 30 | # Kate 31 | *~ 32 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 2 | 3 | SET(PROJECT_NAME_STR commotion) 4 | PROJECT(${PROJECT_NAME_STR}) 5 | SET(NO_OPTIMIZE OFF CACHE BOOL "Disable optimization flags.") 6 | SET(DEBUG OFF CACHE BOOL "Turn on debugging.") 7 | SET(OPENWRT OFF CACHE BOOL "Disable subsystems that are unnecessary for OpenWRT platform.") 8 | SET(TEST ON CACHE BOOL "Build unit tests.") 9 | SET(PLUGINS ON CACHE BOOL "Build plugins.") 10 | SET(COMMOTION_VERSION_MAJOR 0) 11 | SET(COMMOTION_VERSION_MINOR 1) 12 | SET(COMMOTION_VERSION_PATCH 0) 13 | SET(COMMOTION_CONFIGFILE \"/etc/commotion/commotiond.conf\") 14 | SET(COMMOTION_STATEDIR \"/var/run/commotion\") 15 | SET(COMMOTION_PIDFILE \"/var/run/commotiond.pid\") 16 | SET(COMMOTION_MANAGESOCK \"/var/run/commotiond.sock\") 17 | SET(COMMOTION_PLUGINDIR \"/usr/lib/commotion/plugins\") 18 | SET(COMMOTION_PROFILEDIR \"/etc/commotion/profiles.d\") 19 | SET(CMAKE_VERBOSE_MAKEFILE ON) 20 | 21 | SET(COMMON_INCLUDES ${PROJECT_SOURCE_DIR}/src) 22 | 23 | CONFIGURE_FILE( "${CMAKE_SOURCE_DIR}/src/config.h.in" "${CMAKE_SOURCE_DIR}/src/config.h" ) 24 | 25 | ADD_DEFINITIONS(-Os -Wall --std=gnu99 -Wmissing-declarations -DNDEBUG) 26 | 27 | IF(OPENWRT) 28 | ADD_DEFINITIONS(-D_OPENWRT -DUSESYSLOG) 29 | ENDIF() 30 | 31 | IF(DEBUG) 32 | ADD_DEFINITIONS(-g3) 33 | REMOVE_DEFINITIONS(-DNDEBUG) 34 | IF(NO_OPTIMIZE) 35 | REMOVE_DEFINITIONS(-Os) 36 | ADD_DEFINITIONS(-O0) 37 | ENDIF() 38 | ENDIF() 39 | 40 | ADD_SUBDIRECTORY(src) 41 | 42 | IF(TEST) 43 | ENABLE_TESTING() 44 | ADD_SUBDIRECTORY(tests) 45 | ENDIF() 46 | 47 | IF(PLUGINS) 48 | ADD_SUBDIRECTORY(plugins) 49 | ENDIF() 50 | 51 | IF(NOT OPENWRT) 52 | FIND_PACKAGE(Doxygen) 53 | IF(DOXYGEN_FOUND) 54 | CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/doxygen/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) 55 | ADD_CUSTOM_TARGET(doc ALL 56 | ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile 57 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 58 | COMMENT "Generating API documentation with Doxygen" VERBATIM 59 | ) 60 | ENDIF(DOXYGEN_FOUND) 61 | ENDIF() 62 | 63 | INSTALL(FILES files/commotiond.conf DESTINATION /etc/commotion) 64 | INSTALL(DIRECTORY files/profiles.d DESTINATION /etc/commotion) 65 | 66 | # uninstall target 67 | CONFIGURE_FILE( 68 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" 69 | "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" 70 | IMMEDIATE @ONLY) 71 | 72 | ADD_CUSTOM_TARGET(uninstall 73 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) 74 | 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![alt tag](http://img.shields.io/badge/maintainer-jheretic-red.svg)](https://github.com/jheretic) 2 | 3 | commotiond/libcommotion 4 | ======================= 5 | This embedded library and daemon are the start of what will form the new core of the Commotion project on embedded platforms. *This is extremely pre-alpha software that does not do anything yet, but which is in rapid development.* 6 | 7 | Build it 8 | ============ 9 | NOTE: this project uses CMake, so you must have that installed on your system, as well as subversion and sqlite3 header files (libsqlite3-dev). 10 | 11 | 1. Clone the repository. 12 | 2. cd commmotiond 13 | 3. mkdir build 14 | 4. cd build 15 | 5. cmake .. 16 | 6. make 17 | 7. sudo make install 18 | 19 | Commotion components 20 | ====================== 21 | This repository includes 3 main components: 22 | 23 | libcommotion 24 | ------------ 25 | libcommotion is a high level library that contains a C API with all of the tools necessary to create a variety of mesh networks and mesh networking applications, without needing to deal with all of the specifics of configuring each and every type of addressing scheme and mesh networking daemon available. Bindings for other languages like Java or Python are forthcoming. 26 | 27 | commotiond 28 | ---------- 29 | commotiond is an implementation of libcommotion, in the form of a superserver daemon that creates and manages parent processes for a variety of mesh-networking related daemons and services based on a common configuration store. It (will) support a variety of types of plugins and extensions, including: 30 | 31 | * operating-system specific extensions for interfacing with the wireless subsystem 32 | * schemas for mesh network detection 33 | * APIs for different kinds of messaging infrastructures (dbus, ubus, JNI) 34 | * drivers for different kinds of mesh networking daemons (olsrd, babeld, servald) 35 | 36 | commotion 37 | --------- 38 | The commotion application is a simple command-shell interface for managing the commotiond daemon. 39 | 40 | Plugins 41 | ======= 42 | Commotiond currently includes 2 complete plugins: 43 | 44 | serval-dna 45 | ---------- 46 | This plugin uses the libserval library version of [Serval-DNA](https://github.com/opentechinstitute/serval-dna), and runs it as a daemon using commotiond's event loop. It also provides CLI commands and an API for creating and verifying signatures using a serval-dna keyring. 47 | 48 | demo 49 | ---- 50 | This is a barebones plugin that provides an example for other developers to build plugins for commotiond. 51 | -------------------------------------------------------------------------------- /cmake_uninstall.cmake.in: -------------------------------------------------------------------------------- 1 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 3 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") 4 | 5 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) 6 | string(REGEX REPLACE "\n" ";" files "${files}") 7 | foreach(file ${files}) 8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}") 9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 10 | exec_program( 11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" 12 | OUTPUT_VARIABLE rm_out 13 | RETURN_VALUE rm_retval 14 | ) 15 | if(NOT "${rm_retval}" STREQUAL 0) 16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") 17 | endif(NOT "${rm_retval}" STREQUAL 0) 18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.") 20 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") 21 | endforeach(file) 22 | 23 | -------------------------------------------------------------------------------- /files/commotiond.conf: -------------------------------------------------------------------------------- 1 | { 2 | "bind": "/var/run/commotiond.sock", 3 | "state": "/var/run/commotion/", 4 | "pid": "/var/run/commotiond.pid", 5 | "plugins": "/usr/lib/commotion/plugins/", 6 | "profiles": "/etc/commotion/profiles.d/", 7 | "serval_path": "/etc/serval/" 8 | } 9 | -------------------------------------------------------------------------------- /files/profiles.d/example: -------------------------------------------------------------------------------- 1 | { 2 | "ssid": "commotionwireless.net", 3 | "bssid": "02:CA:FF:EE:BA:BE", 4 | "bssidgen": "true", 5 | "channel": "5", 6 | "mode": "adhoc", 7 | "type": "mesh", 8 | "dns": "208.67.222.222", 9 | "domain": "mesh.local", 10 | "ipgen": "true", 11 | "ip": "100.64.0.0", 12 | "netmask": "255.192.0.0", 13 | "ipgenmask": "255.192.0.0", 14 | "wpa": "true", 15 | "wpakey": "c0MM0t10n!r0cks", 16 | "servald": "false", 17 | "servalsid": "", 18 | "announce": "true" 19 | } 20 | -------------------------------------------------------------------------------- /openwrt/etc/config/commotiond: -------------------------------------------------------------------------------- 1 | config daemon 2 | 3 | config node 4 | 5 | -------------------------------------------------------------------------------- /openwrt/etc/init.d/commotiond: -------------------------------------------------------------------------------- 1 | #!/bin/sh /etc/rc.common 2 | 3 | . $IPKG_INSTROOT/lib/functions/commotion.sh 4 | . $IPKG_INSTROOT/lib/functions/network.sh 5 | . $IPKG_INSTROOT/lib/config/uci.sh 6 | 7 | #DEBUG=echo 8 | START=19 9 | STOP=91 10 | EXTRA_COMMANDS="cron" 11 | EXTRA_HELP=" cron Watchdog function meant to be called from cron" 12 | CRON_SERVICES="commotiond olsrd commotion-service-manager dnsmasq" 13 | CRON_THRESHOLD="180" 14 | 15 | boot() { 16 | logger -t commotion.init "Called: boot" 17 | case "$(uci_get wireless @wifi-device[0] disabled 1)" in 18 | 1) 19 | case "$(uci_get wireless @wifi-iface[0] ssid "OpenWrt")" in 20 | "OpenWrt") 21 | rm -f /etc/config/wireless 22 | $DEBUG /sbin/wifi detect > /etc/config/wireless 23 | # Clear out any existing wireless interfaces 24 | $DEBUG uci_load wireless 25 | while [ "$?" != '1' ]; do 26 | logger -t commotion.init "Removing interfaces." 27 | $DEBUG uci_remove wireless @wifi-iface[] 28 | done 29 | $DEBUG uci_commit wireless 30 | logger -t commotion.init "Applied wireless defaults." 31 | ;; 32 | esac 33 | ;; 34 | esac 35 | mkdir -m 0755 -p /var/run/commotion 36 | rm -rf /var/serval-node 37 | ln -s /etc/serval/ /var/serval-node 38 | start 39 | } 40 | 41 | start() { 42 | logger -t commotion.init "Called: start" 43 | local args bind profiles pid statedir id 44 | 45 | config_cb() { 46 | local type="$1" 47 | local name="$2" 48 | 49 | case "$type" in 50 | "daemon") 51 | option_cb() { 52 | local name="$1" 53 | local value="$2" 54 | 55 | case "$name" in 56 | "config") 57 | append args "-b $value" 58 | ;; 59 | "bind") 60 | append args "-b $value" 61 | ;; 62 | "plugins") 63 | append args "-d $value" 64 | ;; 65 | "profiles") 66 | append args "-f $value" 67 | ;; 68 | "id") 69 | append args "-i $value" 70 | ;; 71 | "nodaemonize") 72 | append args "-n $value" 73 | ;; 74 | "pid") 75 | append args "-p $value" 76 | ;; 77 | "statedir") 78 | append args "-s $value" 79 | ;; 80 | "help") 81 | append args "-h" 82 | ;; 83 | esac 84 | } 85 | ;; 86 | "node") 87 | option_cb() { 88 | local name="$1" 89 | local value="$2" 90 | 91 | case "$name" in 92 | "id") 93 | append args "-i $value" 94 | ;; 95 | esac 96 | } 97 | ;; 98 | esac 99 | } 100 | config_load commotiond 101 | 102 | $DEBUG service_start /usr/sbin/commotiond $args 103 | 104 | sleep 1 #allow commotiond to settle 105 | 106 | [ -z "$(uci_get commotiond @node[0] id)" ] && { 107 | echo "Nodeid generation!" 108 | commotion_set_nodeid_from_mac "$(cat /sys/class/ieee80211/phy0/macaddress)" 109 | uci_set commotiond @node[0] id "$(commotion_get_nodeid)" 110 | uci_commit commotiond 111 | } 112 | 113 | reset_cb 114 | config_cb() { 115 | local type="$1" 116 | local name="$2" 117 | 118 | [ "$type" == "interface" ] && { 119 | local proto="$(uci_get network "$name" proto)" 120 | local class="$(uci_get network "$name" class)" 121 | [ "$proto" == "commotion" -a "$class" == "mesh" ] && { 122 | local profile="$(uci_get network "$name" profile)" 123 | network_get_physdev physdev "$name" 124 | [ ! -z "$physdev" ] && [ ! -z "$profile" ] && { 125 | logger -t commotion.init "commotion_up "$physdev" "$profile"" 126 | commotion_up "$physdev" "$profile" 127 | } 128 | } 129 | } 130 | } 131 | config_load network 132 | 133 | } 134 | 135 | stop() { 136 | logger -t commotion.init "Called: stop" 137 | $DEBUG service_stop /usr/sbin/commotiond 138 | } 139 | 140 | cron() { 141 | logger -t commotion.init "Called: cron" 142 | 143 | enabled && { 144 | local uptime=$(awk -F . '{print $1}' /proc/uptime) 145 | [ $uptime -ge $CRON_THRESHOLD ] && [ "$(uci_get setup_wizard settings enabled 1)" == 0 ] && { 146 | [ "$(uci_get_state commotiond @node[0] restarted 0)" == 0 ] && { 147 | logger -t commotion.init "Restarting commotiond $CRON_THRESHOLD seconds after boot." 148 | uci_set_state commotiond @node[0] restarted 1 149 | restart 150 | return 0 151 | } 152 | 153 | for s in $CRON_SERVICES 154 | do 155 | /etc/init.d/"$s" enabled && ! service_check "/usr/sbin/$s" && \ 156 | ( logger -t commotion.init "Restarting $s"; /etc/init.d/"$s" restart ) 157 | done 158 | } 159 | } 160 | } 161 | 162 | -------------------------------------------------------------------------------- /openwrt/etc/uci-defaults/commotiond: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | . /lib/config/uci.sh 4 | 5 | [ -f "/etc/crontabs/root" ] || touch /etc/crontabs/root 6 | 7 | grep -q "commotiond" /etc/crontabs/root || { \ 8 | echo '* * * * * /etc/init.d/commotiond cron' >> /etc/crontabs/root 9 | /etc/init.d/cron restart 10 | } 11 | 12 | [ -z $(uci_get ucitrack @setup_wizard[0]) ] && { \ 13 | uci_add ucitrack setup_wizard 14 | uci_set ucitrack @setup_wizard[0] init commotiond 15 | uci_commit ucitrack 16 | } 17 | 18 | exit 0 19 | -------------------------------------------------------------------------------- /openwrt/lib/netifd/commotion.dhcp.script: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -z "$1" ] && echo "Error: should be run by udhcpc" && exit 1 3 | 4 | . /lib/functions.sh 5 | . /lib/netifd/netifd-proto.sh 6 | . /lib/config/uci.sh 7 | . /lib/functions/commotion.sh 8 | 9 | DEFAULT_LEASE_ZONE="wan" 10 | 11 | set_classless_routes() { 12 | local max=128 13 | local type 14 | while [ -n "$1" -a -n "$2" -a $max -gt 0 ]; do 15 | proto_add_ipv4_route "${1%%/*}" "${1##*/}" "$2" 16 | max=$(($max-1)) 17 | shift 2 18 | done 19 | } 20 | 21 | setup_interface () { 22 | proto_init_update "*" 1 23 | proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}" 24 | # TODO: apply $broadcast 25 | 26 | for i in $router; do 27 | proto_add_ipv4_route 0.0.0.0 0 "$i" 28 | done 29 | 30 | # CIDR STATIC ROUTES (rfc3442) 31 | [ -n "$staticroutes" ] && set_classless_routes $staticroutes 32 | [ -n "$msstaticroutes" ] && set_classless_routes $msstaticroutes 33 | 34 | for dns in $dns; do 35 | proto_add_dns_server "$dns" 36 | done 37 | for domain in $domain; do 38 | proto_add_dns_search "$domain" 39 | done 40 | unset_fwzone "$DHCP_INTERFACE" 41 | set_fwzone "$DHCP_INTERFACE" "$(uci_get network "$DHCP_INTERFACE" lease_zone "$DEFAULT_LEASE_ZONE")" 42 | uci_commit firewall 43 | proto_send_update "$DHCP_INTERFACE" 44 | 45 | # TODO 46 | # [ -n "$ntpsrv" ] && change_state network "$ifc" lease_ntpsrv "$ntpsrv" 47 | # [ -n "$timesvr" ] && change_state network "$ifc" lease_timesrv "$timesvr" 48 | # [ -n "$hostname" ] && change_state network "$ifc" lease_hostname "$hostname" 49 | # [ -n "$timezone" ] && change_state network "$ifc" lease_timezone "$timezone" 50 | } 51 | 52 | deconfig_interface() { 53 | return 54 | } 55 | 56 | case "$1" in 57 | deconfig) 58 | deconfig_interface 59 | ;; 60 | renew|bound) 61 | setup_interface 62 | ;; 63 | esac 64 | 65 | # user rules 66 | [ -f /etc/udhcpc.user ] && . /etc/udhcpc.user 67 | 68 | exit 0 69 | -------------------------------------------------------------------------------- /plugins/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(PLUGINS serval-dna) 2 | 3 | FOREACH(PLUGIN ${PLUGINS}) 4 | ADD_SUBDIRECTORY(${PLUGIN}) 5 | ENDFOREACH(PLUGIN) 6 | -------------------------------------------------------------------------------- /plugins/demo/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(PLUGIN_NAME demo) 2 | SET(PLUGINSRC demo.c) 3 | 4 | INCLUDE_DIRECTORIES(${COMMON_INCLUDES}) 5 | 6 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 7 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins) 8 | 9 | ADD_LIBRARY(${PLUGIN_NAME} SHARED ${PLUGINSRC}) 10 | 11 | TARGET_LINK_LIBRARIES(${PLUGIN_NAME} commotion) 12 | 13 | SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES OUTPUT_NAME commotion_${PLUGIN_NAME}) 14 | 15 | INSTALL(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/commotion/plugins) -------------------------------------------------------------------------------- /plugins/demo/README.md: -------------------------------------------------------------------------------- 1 | Demo plugin for commotiond 2 | ================================ 3 | This is a demo plugin for commotiond. It is intended to provide a skeleton for developing new plugins, 4 | as well as demonstrating their basic structure. 5 | 6 | Dependencies 7 | ------------ 8 | This plugin has no dependencies 9 | 10 | Changelog 11 | --------- 12 | 4/17/2014 - Initial release 13 | 14 | Contact 15 | ------- 16 | Grady Johnson 17 | https://commotionwireless.net 18 | 19 | 20 | GETTING STARTED 21 | 22 | Create a new directory in /commotiond/plugins/YOUR_PLUGIN 23 | 24 | This will house your source code and CMake file. 25 | 26 | BUILDING MAKEFILES WITH CMAKE 27 | 28 | Copy in the CMakeLists.txt file from the demo directory, then edit the variables for PLUGIN_NAME and PLUGIN_SRC. 29 | 30 | Next, go up one directory to /commotiond/plugins and add your plugin to the CMakeLists.txt file there, under: 31 | 32 | SET(PLUGINS serval-dna demo NEW_PLUGIN) 33 | 34 | 35 | PLUGIN FUNCTIONS 36 | 37 | REQUIRED: 38 | int co_plugin_name(co_obj_t *self, co_obj_t **output, co_obj_t *params); 39 | Called by the Commotion daemon via co_plugins_load. This function registers the plugin (and 40 | its included functions) with the list of available plugins. 41 | 42 | int co_plugin_init(co_obj_t *self, co_obj_t **output, co_obj_t *params); 43 | Called by the Commotion daemon via co_plugins_init. This function is used to 44 | initialize the rest of your plugin (setting up data structures, registering commands, etc.) 45 | 46 | OPTIONAL: 47 | int co_plugin_register(co_obj_t *self, co_obj_t **output, co_obj_t *params); 48 | Called by the Commotion daemon via co_plugins_register. This function loads your plugin's 49 | schema to the existing commotion configuration or profile schemas. 50 | 51 | int co_plugin_shutdown(co_obj_t *self, co_obj_t **output, co_obj_t *params); 52 | Called by the Commotion daemon via co_plugins_shutdown. This function is used to gracefully 53 | end any running plugin processes and free allocated memory. 54 | 55 | 56 | -------------------------------------------------------------------------------- /plugins/demo/demo.c: -------------------------------------------------------------------------------- 1 | #include "debug.h" 2 | #include "plugin.h" 3 | #include "list.h" 4 | #include "profile.h" 5 | #include "cmd.h" 6 | #include "tree.h" 7 | 8 | #include "demo.h" 9 | 10 | int echo_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params) 11 | { 12 | CHECK(IS_LIST(params) && co_list_length(params) == 1,"Invalid parameters"); 13 | 14 | char *data; 15 | co_obj_t *input; 16 | co_obj_t *echo; 17 | int ret; 18 | 19 | // get list element 20 | input = co_list_element(params, 0); 21 | 22 | // copy input object data 23 | ret = co_obj_data(&data, input); 24 | CHECK(ret, "Failed to retrieve data."); 25 | 26 | // create new object with same string 27 | echo = co_str8_create(data, strlen(data) + 1, 0); 28 | 29 | // echo string 30 | CMD_OUTPUT("result", echo); 31 | 32 | return 1; 33 | error: 34 | return 0; 35 | } 36 | 37 | 38 | SCHEMA(demo) { 39 | SCHEMA_ADD("demo","enabled"); 40 | return 1; 41 | } 42 | 43 | int demo_register(void) 44 | { 45 | const char name[] = "echo", 46 | usage[] = "echo [string to echo]", 47 | desc[] = "Echo a string."; 48 | 49 | CHECK(co_cmd_register(name, sizeof(name), usage, sizeof(usage), desc,sizeof(desc), echo_handler), "Failed to register commands"); 50 | 51 | return 1; 52 | error: 53 | return 0; 54 | } 55 | 56 | int co_plugin_register(co_obj_t *self, co_obj_t **output, co_obj_t *params) { 57 | DEBUG("Loading demo schema."); 58 | SCHEMA_GLOBAL(demo); // adds to global commotion.conf file 59 | SCHEMA_REGISTER(demo); // adds to profile schema 60 | return 1; 61 | } 62 | 63 | int co_plugin_name(co_obj_t *self, co_obj_t **output, co_obj_t *params) 64 | { 65 | const char name[] = "demo"; 66 | CHECK((*output = co_str8_create(name,strlen(name)+1,0)),"Failed to create plugin name"); 67 | return 1; 68 | error: 69 | return 0; 70 | } 71 | 72 | int co_plugin_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) 73 | { 74 | int ret = 0; 75 | ret = demo_register(); 76 | return ret; 77 | } -------------------------------------------------------------------------------- /plugins/demo/demo.h: -------------------------------------------------------------------------------- 1 | int echo_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params); 2 | 3 | int demo_register(void); 4 | 5 | int co_plugin_register(co_obj_t *self, co_obj_t **output, co_obj_t *params); 6 | 7 | int co_plugin_name(co_obj_t *self, co_obj_t **output, co_obj_t *params); 8 | 9 | int co_plugin_init(co_obj_t *self, co_obj_t **output, co_obj_t *params); -------------------------------------------------------------------------------- /plugins/olsrd/olsrd.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file olsrd.h 4 | * @brief OLSRd configuration and process management 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #include 34 | #include "process.h" 35 | #include "util.h" 36 | #include "obj.h" 37 | 38 | #define OLSR_HNA4 (1 << 0) 39 | #define OLSR_HNA6 (1 << 1) 40 | #define OLSR_IFACE_MESH (1 << 0) 41 | #define OLSR_IFACE_ETHER (1 << 1) 42 | 43 | /** 44 | * @struct co_olsrd_process_t 45 | * @brief contains the OLSRd process protocol 46 | */ 47 | typedef struct { 48 | co_process_t proto; 49 | } co_olsrd_process_t; 50 | 51 | /** 52 | * @struct co_olsrd_conf_item_t 53 | * @brief contains the key and value for configuring OLSRd for Commotion 54 | */ 55 | typedef struct { 56 | char *key; 57 | char *value; 58 | } co_olsrd_conf_item_t; 59 | 60 | /** 61 | * @struct co_olsrd_conf_plugin_t 62 | * @brief contains the number of configuration items for OLSRd 63 | */ 64 | typedef struct { 65 | char *name; 66 | co_olsrd_conf_item_t **attr; 67 | int num_attr; 68 | } co_olsrd_conf_plugin_t; 69 | 70 | /** 71 | * @struct co_olsrd_conf_iface_t 72 | * @brief contains interace configuration settings for OLSR, including interface name, mode and IPv4 broadcast message 73 | */ 74 | typedef struct { 75 | char *ifname; 76 | int mode; 77 | char *Ipv4Broadcast; 78 | } co_olsrd_conf_iface_t; 79 | 80 | /** 81 | * @struct co_olsrd_conf_hna_t 82 | * @brief contains host network address settings, including family, address and netmask 83 | */ 84 | typedef struct { 85 | int family; 86 | char *address; 87 | char *netmask; 88 | } co_olsrd_conf_hna_t; 89 | 90 | /** 91 | * @brief adds an interface to OLSRd 92 | * @param name name of the interface to be added 93 | * @param mode network mode for interface 94 | * @param Ipv4Broadcast IPv4 broadcast address (node address, using netmask as last octet) 95 | */ 96 | int co_olsrd_add_iface(const char* name, int mode, const char *Ipv4Broadcast); 97 | 98 | /** 99 | * @brief removes an interface from OLSRd 100 | * @param name name of the interface to be removed 101 | * @param mode network mode for interface 102 | * @param Ipv4Broadcast IPv4 broadcast address (node address, using netmask as last octet) 103 | */ 104 | int co_olsrd_remove_iface(char* name, int mode, char *Ipv4Broadcast); 105 | 106 | /** 107 | * @brief adds a host network address to OLSRd 108 | * @param family the address family 109 | * @param address the network address for the interface 110 | * @param netmask the netmask for the interface 111 | */ 112 | int co_olsrd_add_hna(const int family, const char *address, const char *netmask); 113 | 114 | /** 115 | * @brief remves a host network address from OLSRd 116 | * @param family the address family 117 | * @param address the network address for the interface 118 | * @param netmask the netmask for the interface 119 | */ 120 | int co_olsrd_remove_hna(int family, char *address, char *netmask); 121 | 122 | /** 123 | * @brief prints OLSR configuration info from file (currently unimplemented) 124 | * @param filename the configuration file 125 | */ 126 | int co_olsrd_print_conf(const char *filename); 127 | 128 | /** 129 | * @brief initiates the OLSR daemon when a new process gets created (currently unimplemented) 130 | * @param self process to be called 131 | */ 132 | int co_olsrd_init(co_obj_t *self); 133 | -------------------------------------------------------------------------------- /plugins/serval-dna/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | INCLUDE (CheckFunctionExists) 2 | CHECK_FUNCTION_EXISTS (bcopy HAVE_BCOPY) 3 | CHECK_FUNCTION_EXISTS (bzero HAVE_BZERO) 4 | CHECK_FUNCTION_EXISTS (bcmp HAVE_BCMP) 5 | CHECK_FUNCTION_EXISTS (lseek64 HAVE_LSEEK64) 6 | INCLUDE (CheckIncludeFiles) 7 | CHECK_INCLUDE_FILES (arpa/inet.h HAVE_ARPA_INET_H) 8 | CHECK_INCLUDE_FILES (poll.h HAVE_POLL_H) 9 | CHECK_INCLUDE_FILES (sys/socket.h HAVE_SYS_SOCKET_H) 10 | CHECK_INCLUDE_FILES (netinet/in.h HAVE_NETINET_IN_H) 11 | 12 | SET(DEFAULT_SID \"0000000000000000000000000000000000000000000000000000000000000000\") 13 | SET(DEFAULT_MDP_PATH \"/etc/commotion/keys.d/mdp.keyring/serval.keyring\") 14 | SET(DEFAULT_SERVAL_PATH \"/var/serval-node\") 15 | 16 | IF(OPENWRT) 17 | SET(DEFAULT_SERVAL_PATH \"/etc/serval\") 18 | ENDIF() 19 | 20 | CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/plugins/serval-dna/serval-config.h.in ${CMAKE_SOURCE_DIR}/plugins/serval-dna/serval-config.h) 21 | 22 | SET(PLUGIN_NAME serval-dna) 23 | SET(PLUGINSRC serval-dna.c crypto.c commands.c keyring.c olsr_mdp.c) 24 | SET(CLIENT_NAME serval-client) 25 | SET(CLIENTSRC serval-client.c crypto.c keyring.c) 26 | SET(SAS_NAME serval-sas) 27 | SET(SASSRC sas_request.c) 28 | 29 | INCLUDE_DIRECTORIES(${COMMON_INCLUDES}) 30 | INCLUDE_DIRECTORIES("/usr/include/serval") 31 | 32 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 33 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins) 34 | 35 | ADD_LIBRARY(${PLUGIN_NAME} SHARED ${PLUGINSRC}) 36 | ADD_EXECUTABLE(${CLIENT_NAME} ${CLIENTSRC}) 37 | ADD_LIBRARY(${SAS_NAME} SHARED ${SASSRC}) 38 | 39 | TARGET_LINK_LIBRARIES(${PLUGIN_NAME} serval commotion) 40 | TARGET_LINK_LIBRARIES(${CLIENT_NAME} serval commotion) 41 | TARGET_LINK_LIBRARIES(${SAS_NAME} mdpclient commotion) 42 | 43 | SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES OUTPUT_NAME commotion_${PLUGIN_NAME}) 44 | SET_TARGET_PROPERTIES(${SAS_NAME} PROPERTIES OUTPUT_NAME commotion_${SAS_NAME}) 45 | SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES COMPILE_FLAGS -DSVL_DAEMON) 46 | 47 | INSTALL(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION lib/commotion/plugins) 48 | INSTALL(TARGETS ${CLIENT_NAME} RUNTIME DESTINATION bin) 49 | INSTALL(TARGETS ${SAS_NAME} LIBRARY DESTINATION lib) -------------------------------------------------------------------------------- /plugins/serval-dna/README.md: -------------------------------------------------------------------------------- 1 | Serval-DNA plugin for commotiond 2 | ================================ 3 | This plugin builds three components: 4 | 5 | 1. libcommotion_serval-dna - This is the main plugin library that 6 | re-implements the [Serval][] Distributed Numbering Architecture 7 | (serval-dna) daemon. 8 | 2. serval-client - This is a client program that offers all of 9 | serval-dna's built-in commands, as well as signing and signature 10 | verification using Serval keys. 11 | 3. libcommotion_serval-sas - A library that implements a minimal 12 | MDP client for fetching an SAS signing key over the MDP overlay 13 | network. This will be deprecated once commotiond has a more full- 14 | featured event loop. 15 | 16 | Dependencies 17 | ------------ 18 | This plugin depends on the serval-dna library, libservald. 19 | 20 | Changelog 21 | --------- 22 | 12/18/2013 - Initial release 23 | 24 | Contact 25 | ------- 26 | Dan Staples (dismantl) 27 | https://commotionwireless.net 28 | 29 | [Serval]: https://github.com/servalproject/serval-dna/ -------------------------------------------------------------------------------- /plugins/serval-dna/commands.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file commands.c 3 | * @brief command registration 4 | * 5 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 6 | * 7 | * @internal 8 | * Created 12/18/2013 9 | * Compiler gcc/g++ 10 | * Company The Open Technology Institute 11 | * Copyright Copyright (c) 2013, Dan Staples 12 | * 13 | * This file is part of Commotion, Copyright (c) 2013, Josh King 14 | * 15 | * Commotion is free software: you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published 17 | * by the Free Software Foundation, either version 3 of the License, 18 | * or (at your option) any later version. 19 | * 20 | * Commotion is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | * GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with Commotion. If not, see . 27 | * 28 | * ===================================================================================== 29 | */ 30 | 31 | #include "serval-config.h" 32 | #include 33 | 34 | #include "cmd.h" 35 | 36 | #include "serval-dna.h" 37 | #include "crypto.h" 38 | #include "olsr_mdp.h" 39 | #include "commands.h" 40 | 41 | /* used to store error messages to pass in response to client commands */ 42 | co_obj_t *err_msg = NULL; 43 | int collect_errors = 0; 44 | 45 | int 46 | serval_daemon_register(void) 47 | { 48 | /** 49 | * name: serval-daemon 50 | * param[0] : start|stop|reload (co_str8_t) 51 | */ 52 | 53 | const char name[] = "serval-daemon", 54 | // usage[] = "serval-daemon start|stop|reload", 55 | // desc[] = "Start or stop the Serval daemon, or reload the keyring file"; 56 | usage[] = "serval-daemon reload", 57 | desc[] = "Reload the keyring file"; 58 | 59 | CHECK(co_cmd_register(name,sizeof(name),usage,sizeof(usage),desc,sizeof(desc),serval_daemon_handler),"Failed to register commands"); 60 | 61 | return 1; 62 | error: 63 | return 0; 64 | } 65 | 66 | int 67 | serval_crypto_register(void) 68 | { 69 | /** name: serval-crypto 70 | * param[0] - param[3]: (co_str?_t) 71 | */ 72 | 73 | const char name[] = "serval-crypto", 74 | usage[] = "serval-crypto sign [] [keyring=]\n" 75 | "serval-crypto verify ", 76 | desc[] = "Serval-crypto utilizes Serval's crypto API to:\n" 77 | " * Sign any arbitrary text using a Serval key. If no Serval key ID (SID) is given,\n" 78 | " a new key will be created on the default Serval keyring.\n" 79 | " * Verify any arbitrary text, a signature, and a Serval signing key (SAS), and will\n" 80 | " determine if the signature is valid."; 81 | 82 | int reg_ret = co_cmd_register(name, 83 | sizeof(name), 84 | usage, 85 | sizeof(usage), 86 | desc, 87 | sizeof(desc), 88 | serval_crypto_handler); 89 | CHECK(reg_ret, "Failed to register commands"); 90 | 91 | return 1; 92 | error: 93 | return 0; 94 | } 95 | 96 | int 97 | olsrd_mdp_register(void) 98 | { 99 | /** 100 | * name: mdp-init 101 | * param[0] : (co_str16_t) 102 | * param[1] : (co_str8_t) 103 | */ 104 | CHECK(co_cmd_register("mdp-init", sizeof("mdp-init"), "", 1, "", 1, olsrd_mdp_init), "Failed to register mdp-init command"); 105 | 106 | /** 107 | * name: mdp-sign 108 | * param[0] : key (co_bin8_t) 109 | * param[1] : data (co_bin?_t) 110 | */ 111 | CHECK(co_cmd_register("mdp-sign", sizeof("mdp-sign"), "", 1, "", 1, olsrd_mdp_sign), "Failed to register mdp-sign command"); 112 | 113 | return 1; 114 | error: 115 | return 0; 116 | } -------------------------------------------------------------------------------- /plugins/serval-dna/commands.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file commands.h 3 | * @brief command registration 4 | * 5 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 6 | * 7 | * @internal 8 | * Created 12/18/2013 9 | * Compiler gcc/g++ 10 | * Company The Open Technology Institute 11 | * Copyright Copyright (c) 2013, Dan Staples 12 | * 13 | * This file is part of Commotion, Copyright (c) 2013, Josh King 14 | * 15 | * Commotion is free software: you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published 17 | * by the Free Software Foundation, either version 3 of the License, 18 | * or (at your option) any later version. 19 | * 20 | * Commotion is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | * GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with Commotion. If not, see . 27 | * 28 | * ===================================================================================== 29 | */ 30 | 31 | #ifndef __CO_SERVAL_COMMANDS_H 32 | #define __CO_SERVAL_COMMANDS_H 33 | 34 | int serval_daemon_register(void); 35 | int serval_crypto_register(void); 36 | int olsrd_mdp_register(void); 37 | 38 | #endif -------------------------------------------------------------------------------- /plugins/serval-dna/crypto.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file crypto.h 3 | * @brief serval-dna plugin functionality for signing/verifying 4 | * using Serval keys 5 | * 6 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 7 | * 8 | * @internal 9 | * Created 12/18/2013 10 | * Compiler gcc/g++ 11 | * Company The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Dan Staples 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published 18 | * by the Free Software Foundation, either version 3 of the License, 19 | * or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | 32 | #ifndef __CO_SERVAL_CRYPTO_H 33 | #define __CO_SERVAL_CRYPTO_H 34 | 35 | #include 36 | #include 37 | 38 | #include "serval-config.h" 39 | #include 40 | #include 41 | #include 42 | 43 | #include "obj.h" 44 | 45 | #define BUF_SIZE 1024 46 | #define crypto_sign_PUBLICKEYBYTES crypto_sign_edwards25519sha512batch_PUBLICKEYBYTES 47 | #define crypto_sign_SECRETKEYBYTES crypto_sign_edwards25519sha512batch_SECRETKEYBYTES 48 | #define SIGNATURE_BYTES crypto_sign_edwards25519sha512batch_BYTES 49 | 50 | typedef struct svl_keyring svl_keyring; 51 | 52 | typedef struct svl_crypto_ctx { 53 | char *keyring_path; 54 | size_t keyring_len; 55 | svl_keyring *keyring; 56 | unsigned char sid[SID_SIZE]; // SID public key 57 | unsigned char sas_public[crypto_sign_PUBLICKEYBYTES]; // SAS public key 58 | unsigned char sas_private[crypto_sign_SECRETKEYBYTES]; // SAS private key 59 | unsigned char signature[SIGNATURE_BYTES]; 60 | unsigned char *msg; // byte array used to create signature 61 | size_t msg_len; 62 | } svl_crypto_ctx; 63 | 64 | svl_crypto_ctx *svl_crypto_ctx_new(void); 65 | void svl_crypto_ctx_free(svl_crypto_ctx *ctx); 66 | 67 | int iszero(unsigned char *buf, size_t len); 68 | void stowSid(unsigned char *packet, int ofs, const char *sid); 69 | 70 | int serval_crypto_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params); 71 | int cmd_serval_sign(svl_crypto_ctx *ctx); 72 | int cmd_serval_verify(svl_crypto_ctx *ctx); 73 | int serval_create_signature(svl_crypto_ctx *ctx); 74 | 75 | #endif -------------------------------------------------------------------------------- /plugins/serval-dna/keyring.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file keyring.h 3 | * @brief functions for managing serval-dna keyrings 4 | * 5 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 6 | * 7 | * @internal 8 | * Created 12/18/2013 9 | * Compiler gcc/g++ 10 | * Company The Open Technology Institute 11 | * Copyright Copyright (c) 2013, Dan Staples 12 | * 13 | * This file is part of Commotion, Copyright (c) 2013, Josh King 14 | * 15 | * Commotion is free software: you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published 17 | * by the Free Software Foundation, either version 3 of the License, 18 | * or (at your option) any later version. 19 | * 20 | * Commotion is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | * GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with Commotion. If not, see . 27 | * 28 | * ===================================================================================== 29 | */ 30 | 31 | #ifndef __CO_SERVAL_KEYRING_H 32 | #define __CO_SERVAL_KEYRING_H 33 | 34 | #include "crypto.h" 35 | 36 | #define KEYRING_PIN NULL 37 | 38 | typedef int (*svl_keyring_update)(svl_crypto_ctx *); 39 | 40 | int serval_open_keyring(svl_crypto_ctx *ctx, svl_keyring_update update); 41 | void serval_close_keyring(svl_crypto_ctx *ctx); 42 | int serval_reload_keyring(svl_crypto_ctx *ctx); 43 | int serval_keyring_add_identity(svl_crypto_ctx *ctx); 44 | keyring_file *serval_get_keyring_file(svl_crypto_ctx *ctx); 45 | int serval_extract_sas(svl_crypto_ctx *ctx); 46 | 47 | #endif -------------------------------------------------------------------------------- /plugins/serval-dna/olsr_mdp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file olsr_mdp.h 3 | * @brief command handlers for mdp plugin for olsrd 4 | * 5 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 6 | * 7 | * @internal 8 | * Created 12/18/2013 9 | * Compiler gcc/g++ 10 | * Company The Open Technology Institute 11 | * Copyright Copyright (c) 2013, Dan Staples 12 | * 13 | * This file is part of Commotion, Copyright (c) 2013, Josh King 14 | * 15 | * Commotion is free software: you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published 17 | * by the Free Software Foundation, either version 3 of the License, 18 | * or (at your option) any later version. 19 | * 20 | * Commotion is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | * GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with Commotion. If not, see . 27 | * 28 | * ===================================================================================== 29 | */ 30 | 31 | #include "serval-config.h" 32 | #include 33 | #include 34 | #include 35 | 36 | #include "obj.h" 37 | #include "list.h" 38 | #include "cmd.h" 39 | #include "tree.h" 40 | 41 | #include "serval-dna.h" 42 | #include "crypto.h" 43 | #include "keyring.h" 44 | #include "olsr_mdp.h" 45 | 46 | int 47 | olsrd_mdp_init(co_obj_t *self, co_obj_t **output, co_obj_t *params) 48 | { 49 | svl_crypto_ctx *ctx = NULL; 50 | CHECK(IS_LIST(params) && co_list_length(params) == 2, "Invalid params"); 51 | 52 | ssize_t s = co_str_len(co_list_element(params, 1)); 53 | CHECK(s > 0, "Invalid params"); 54 | size_t sid_len = s; 55 | char *sid_str = _LIST_ELEMENT(params, 1); 56 | 57 | CHECK(sid_len == (2 * SID_SIZE) + 1 && str_is_subscriber_id(sid_str) == 1, "Invalid SID"); 58 | 59 | ctx = svl_crypto_ctx_new(); 60 | 61 | stowSid(ctx->sid, 0, sid_str); 62 | 63 | ctx->keyring_path = _LIST_ELEMENT(params, 0); 64 | s = co_str_len(co_list_element(params, 0)) - 1; 65 | CHECK(s > 0, "Invalid params"); 66 | ctx->keyring_len = s; 67 | CHECK(ctx->keyring_len < PATH_MAX,"Keyring path too long"); 68 | 69 | CHECK(serval_open_keyring(ctx, NULL), "Failed to initialize Serval keyring"); 70 | 71 | CHECK(serval_extract_sas(ctx), "Failed to fetch SAS keys"); 72 | 73 | co_obj_t *key = co_bin8_create((char*)ctx->sas_private, crypto_sign_SECRETKEYBYTES, 0); 74 | CHECK_MEM(key); 75 | CMD_OUTPUT("key", key); 76 | 77 | return 1; 78 | error: 79 | if (ctx) 80 | svl_crypto_ctx_free(ctx); 81 | return 0; 82 | } 83 | 84 | int 85 | olsrd_mdp_sign(co_obj_t *self, co_obj_t **output, co_obj_t *params) 86 | { 87 | int ret = 0; 88 | svl_crypto_ctx *ctx = svl_crypto_ctx_new(); 89 | 90 | /** skipping some error checking for performance reasons */ 91 | 92 | // CHECK(IS_LIST(params) && co_list_length(params) == 2, "Invalid params"); 93 | 94 | ssize_t s = co_obj_data((char**)&ctx->msg, co_list_element(params, 1)); 95 | CHECK(s > 0, "Invalid message"); 96 | ctx->msg_len = s; 97 | 98 | memcpy(ctx->sas_private,_LIST_ELEMENT(params, 0),crypto_sign_SECRETKEYBYTES); 99 | 100 | CHECK(serval_create_signature(ctx), "Failed to sign OLSRd packet"); 101 | 102 | co_obj_t *sig = co_bin8_create((char*)ctx->signature, SIGNATURE_BYTES, 0); 103 | CHECK_MEM(sig); 104 | CMD_OUTPUT("sig", sig); 105 | 106 | ret = 1; 107 | error: 108 | svl_crypto_ctx_free(ctx); 109 | return ret; 110 | } 111 | -------------------------------------------------------------------------------- /plugins/serval-dna/olsr_mdp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file olsr_mdp.h 3 | * @brief command handlers for mdp plugin for olsrd 4 | * 5 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 6 | * 7 | * @internal 8 | * Created 12/18/2013 9 | * Compiler gcc/g++ 10 | * Company The Open Technology Institute 11 | * Copyright Copyright (c) 2013, Dan Staples 12 | * 13 | * This file is part of Commotion, Copyright (c) 2013, Josh King 14 | * 15 | * Commotion is free software: you can redistribute it and/or modify 16 | * it under the terms of the GNU General Public License as published 17 | * by the Free Software Foundation, either version 3 of the License, 18 | * or (at your option) any later version. 19 | * 20 | * Commotion is distributed in the hope that it will be useful, 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | * GNU General Public License for more details. 24 | * 25 | * You should have received a copy of the GNU General Public License 26 | * along with Commotion. If not, see . 27 | * 28 | * ===================================================================================== 29 | */ 30 | 31 | #ifndef __CO_SERVAL_OLSR_H 32 | #define __CO_SERVAL_OLSR_H 33 | 34 | int olsrd_mdp_init(co_obj_t *self, co_obj_t **output, co_obj_t *params); 35 | int olsrd_mdp_sign(co_obj_t *self, co_obj_t **output, co_obj_t *params); 36 | 37 | #endif -------------------------------------------------------------------------------- /plugins/serval-dna/sas_request.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sas_request.c 3 | * @brief library for fetching a Serval SAS key over the MDP 4 | * overlay network 5 | * 6 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 7 | * 8 | * @internal 9 | * Created 12/18/2013 10 | * Compiler gcc/g++ 11 | * Company The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Dan Staples 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published 18 | * by the Free Software Foundation, either version 3 of the License, 19 | * or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include "serval-config.h" 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | #include "sas_request.h" 55 | #include "debug.h" 56 | 57 | static const char __hexdigit[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 58 | 59 | static char *__tohex(char *dstHex, const unsigned char *srcBinary, size_t bytes) 60 | { 61 | char *p; 62 | for (p = dstHex; bytes--; ++srcBinary) { 63 | *p++ = __hexdigit[*srcBinary >> 4]; 64 | *p++ = __hexdigit[*srcBinary & 0xf]; 65 | } 66 | *p = '\0'; 67 | return dstHex; 68 | } 69 | 70 | inline static int __hexvalue(char c) 71 | { 72 | if (c >= '0' && c <= '9') return c - '0'; 73 | if (c >= 'A' && c <= 'F') return c - 'A' + 10; 74 | if (c >= 'a' && c <= 'f') return c - 'a' + 10; 75 | return -1; 76 | } 77 | 78 | static size_t __fromhex(unsigned char *dstBinary, const char *srcHex, size_t nbinary) 79 | { 80 | size_t count = 0; 81 | while (count != nbinary) { 82 | unsigned char high = __hexvalue(*srcHex++); 83 | if (high & 0xf0) return -1; 84 | unsigned char low = __hexvalue(*srcHex++); 85 | if (low & 0xf0) return -1; 86 | dstBinary[count++] = (high << 4) + low; 87 | } 88 | return count; 89 | } 90 | 91 | static int __fromhexstr(unsigned char *dstBinary, const char *srcHex, size_t nbinary) 92 | { 93 | return (__fromhex(dstBinary, srcHex, nbinary) == nbinary && srcHex[nbinary * 2] == '\0') ? 0 : -1; 94 | } 95 | 96 | int keyring_send_sas_request_client(const char *sid_str, 97 | const size_t sid_len, 98 | char *sas_buf, 99 | const size_t sas_buf_len){ 100 | int sent, found = 0, ret = 0, mdp_sockfd = -1; 101 | int siglen=SID_SIZE+crypto_sign_edwards25519sha512batch_BYTES; 102 | sid_t srcsid; 103 | unsigned char dstsid[SID_SIZE] = {0}; 104 | unsigned char signature[siglen]; 105 | time_ms_t now = gettime_ms(); 106 | 107 | CHECK_MEM(sas_buf); 108 | CHECK(sas_buf_len >= 2 * SAS_SIZE + 1, "Insufficient SAS buffer"); 109 | 110 | CHECK(sid_len == 2 * SID_SIZE && __fromhexstr(dstsid, sid_str, SID_SIZE) == 0, 111 | "Invalid SID"); 112 | 113 | CHECK((mdp_sockfd = overlay_mdp_client_socket()) >= 0,"Cannot create MDP socket"); 114 | 115 | CHECK(overlay_mdp_getmyaddr(mdp_sockfd, 0, &srcsid) == 0, "Could not get local address"); 116 | 117 | int client_port = 32768 + (random() & 32767); 118 | CHECK(overlay_mdp_bind(mdp_sockfd, &srcsid, client_port) == 0, 119 | "Failed to bind to client socket"); 120 | 121 | /* request mapping (send request auth-crypted). */ 122 | overlay_mdp_frame mdp; 123 | memset(&mdp,0,sizeof(mdp)); 124 | 125 | mdp.packetTypeAndFlags=MDP_TX; 126 | mdp.out.queue=OQ_MESH_MANAGEMENT; 127 | memmove(mdp.out.dst.sid.binary,dstsid,SID_SIZE); 128 | mdp.out.dst.port=MDP_PORT_KEYMAPREQUEST; 129 | mdp.out.src.port=client_port; 130 | memmove(mdp.out.src.sid.binary,srcsid.binary,SID_SIZE); 131 | mdp.out.payload_length=1; 132 | mdp.out.payload[0]=KEYTYPE_CRYPTOSIGN; 133 | 134 | sent = overlay_mdp_send(mdp_sockfd, &mdp, 0,0); 135 | if (sent) { 136 | DEBUG("Failed to send SAS resolution request: %d", sent); 137 | CHECK(mdp.packetTypeAndFlags != MDP_ERROR,"MDP Server error #%d: '%s'",mdp.error.error,mdp.error.message); 138 | } 139 | 140 | time_ms_t timeout = now + 5000; 141 | 142 | while(now0) { 147 | int ttl=-1; 148 | if (overlay_mdp_recv(mdp_sockfd, &mdp, client_port, &ttl)==0) { 149 | switch(mdp.packetTypeAndFlags&MDP_TYPE_MASK) { 150 | case MDP_ERROR: 151 | ERROR("overlay_mdp_recv: %s (code %d)", mdp.error.message, mdp.error.error); 152 | break; 153 | case MDP_TX: 154 | { 155 | DEBUG("Received SAS mapping response"); 156 | found = 1; 157 | break; 158 | } 159 | break; 160 | default: 161 | DEBUG("overlay_mdp_recv: Unexpected MDP frame type 0x%x", mdp.packetTypeAndFlags); 162 | break; 163 | } 164 | if (found) break; 165 | } 166 | } 167 | now=gettime_ms(); 168 | } 169 | 170 | unsigned keytype = mdp.out.payload[0]; 171 | 172 | CHECK(keytype == KEYTYPE_CRYPTOSIGN,"Ignoring SID:SAS mapping with unsupported key type %u", keytype); 173 | 174 | CHECK(mdp.out.payload_length >= 1 + SAS_SIZE,"Truncated key mapping announcement? payload_length: %d", mdp.out.payload_length); 175 | 176 | unsigned char *sas_public=&mdp.out.payload[1]; 177 | unsigned char *compactsignature = &mdp.out.payload[1+SAS_SIZE]; 178 | 179 | /* reconstitute signed SID for verification */ 180 | memmove(&signature[0],&compactsignature[0],64); 181 | memmove(&signature[64],&mdp.out.src.sid.binary[0],SID_SIZE); 182 | 183 | CHECK(__tohex(sas_buf,sas_public,SAS_SIZE),"Failed to convert signing key"); 184 | sas_buf[2*SAS_SIZE] = '\0'; 185 | 186 | ret = 1; 187 | 188 | error: 189 | if (mdp_sockfd != -1) 190 | overlay_mdp_client_close(mdp_sockfd); 191 | return ret; 192 | } -------------------------------------------------------------------------------- /plugins/serval-dna/sas_request.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file sas_request.h 3 | * @brief library for fetching a Serval SAS key over the MDP 4 | * overlay network 5 | * 6 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 7 | * 8 | * @internal 9 | * Created 12/18/2013 10 | * Compiler gcc/g++ 11 | * Company The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Dan Staples 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published 18 | * by the Free Software Foundation, either version 3 of the License, 19 | * or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | 32 | #include "serval-config.h" 33 | #include 34 | 35 | #ifndef __CO_SERVAL_SAS_REQUEST_H 36 | #define __CO_SERVAL_SAS_REQUEST_H 37 | 38 | #define SID_SIZE 32 39 | #define SAS_SIZE 32 40 | 41 | int keyring_send_sas_request_client(const char *sid_str, 42 | const size_t sid_len, 43 | char *sas_buf, 44 | const size_t sas_buf_len); 45 | 46 | #endif -------------------------------------------------------------------------------- /plugins/serval-dna/serval-config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef __CO_SERVAL_CONFIG_H 2 | #define __CO_SERVAL_CONFIG_H 3 | 4 | #define HAVE_BCOPY ${HAVE_BCOPY} 5 | #define HAVE_BZERO ${HAVE_BZERO} 6 | #define HAVE_BCMP ${HAVE_BCMP} 7 | #define HAVE_LSEEK64 ${HAVE_LSEEK64} 8 | #define HAVE_ARPA_INET_H ${HAVE_ARPA_INET_H} 9 | #define HAVE_POLL_H ${HAVE_POLL_H} 10 | #define HAVE_SYS_SOCKET_H ${HAVE_SYS_SOCKET_H} 11 | #define HAVE_NETINET_IN_H ${HAVE_NETINET_IN_H} 12 | 13 | #define DEFAULT_SID ${DEFAULT_SID} 14 | #define DEFAULT_MDP_PATH ${DEFAULT_MDP_PATH} 15 | #define DEFAULT_SERVAL_PATH ${DEFAULT_SERVAL_PATH} 16 | #define PATH_MAX 4096 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /plugins/serval-dna/serval-dna.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file serval-dna.h 3 | * @brief re-implementation of the serval-dna daemon as a 4 | * commotiond plugin 5 | * 6 | * @author Dan Staples (dismantl), danstaples@opentechinstitute.org 7 | * 8 | * @internal 9 | * Created 12/18/2013 10 | * Compiler gcc/g++ 11 | * Company The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Dan Staples 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published 18 | * by the Free Software Foundation, either version 3 of the License, 19 | * or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | 32 | #ifndef __CO_SERVAL_DNA_H 33 | #define __CO_SERVAL_DNA_H 34 | 35 | #include 36 | 37 | #include "list.h" 38 | 39 | #ifdef SVL_DAEMON 40 | 41 | extern int collect_errors; 42 | extern co_obj_t *err_msg; 43 | 44 | #undef CHECK 45 | #define CHECK(A, M, ...) if(!(A)) { \ 46 | ERROR(M, ##__VA_ARGS__); \ 47 | if (collect_errors) { \ 48 | if (err_msg == NULL) \ 49 | err_msg = co_list16_create(); \ 50 | if (err_msg) { \ 51 | char *msg = NULL; \ 52 | int len = snprintf(NULL, 0, M, ##__VA_ARGS__); \ 53 | msg = calloc(len + 1,sizeof(char)); \ 54 | if (msg) { \ 55 | sprintf(msg, M, ##__VA_ARGS__); \ 56 | co_obj_t *str = NULL; \ 57 | if (len < UINT8_MAX) { \ 58 | str = co_str8_create(msg,len+1,0); \ 59 | if (str) co_list_append(err_msg, str); \ 60 | } else if (len < UINT16_MAX) { \ 61 | str = co_str16_create(msg,len+1,0); \ 62 | if (str) co_list_append(err_msg, str); \ 63 | } else if (len < UINT32_MAX) { \ 64 | str = co_str32_create(msg,len+1,0); \ 65 | if (str) co_list_append(err_msg, str); \ 66 | } \ 67 | free(msg); \ 68 | } \ 69 | } else { \ 70 | ERROR("Out of memory."); \ 71 | } \ 72 | } \ 73 | errno=0; goto error; \ 74 | } 75 | 76 | #define CLEAR_ERR() err_msg = NULL; collect_errors = 1; 77 | #define INS_ERROR() if (err_msg) { CMD_OUTPUT("errors",err_msg); } collect_errors = 0; 78 | 79 | #else 80 | 81 | #define CLEAR_ERR() 82 | #define INS_ERROR() 83 | 84 | #endif 85 | 86 | int co_plugin_register(co_obj_t *self, co_obj_t **output, co_obj_t *params); 87 | int co_plugin_init(co_obj_t *self, co_obj_t **output, co_obj_t *params); 88 | int co_plugin_name(co_obj_t *self, co_obj_t **output, co_obj_t *params); 89 | int co_plugin_shutdown(co_obj_t *self, co_obj_t **output, co_obj_t *params); 90 | int serval_socket_cb(co_obj_t *self, co_obj_t *context); 91 | int serval_timer_cb(co_obj_t *self, co_obj_t **output, co_obj_t *context); 92 | int serval_schema(co_obj_t *self, co_obj_t **output, co_obj_t *params); 93 | int serval_daemon_handler(co_obj_t *self, co_obj_t **output, co_obj_t *params); 94 | 95 | #endif -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 2 | SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 3 | SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) 4 | 5 | SET(DAEMONSRC daemon.c) 6 | SET(LIBSRC debug.h extern/wpa_ctrl.c extern/wpa_ctrl.h extern/halloc.c extern/halloc.h iface.c iface.h loop.c loop.h msg.c msg.h process.c process.h profile.c profile.h socket.c socket.h util.c util.h id.c id.h obj.c obj.h list.c list.h tree.c tree.h cmd.c cmd.h plugin.c plugin.h extern/jsmn.c extern/jsmn.h commotion.c commotion.h extern/md5.c extern/md5.h) 7 | SET(CLIENTSRC client.c) 8 | 9 | ADD_EXECUTABLE(daemon ${DAEMONSRC}) 10 | ADD_EXECUTABLE(client ${CLIENTSRC}) 11 | ADD_LIBRARY(commotion SHARED ${LIBSRC}) 12 | 13 | TARGET_LINK_LIBRARIES(commotion rt dl) 14 | TARGET_LINK_LIBRARIES(daemon commotion) 15 | TARGET_LINK_LIBRARIES(client commotion) 16 | 17 | SET_TARGET_PROPERTIES(daemon PROPERTIES OUTPUT_NAME commotiond) 18 | SET_TARGET_PROPERTIES(client PROPERTIES OUTPUT_NAME commotion) 19 | 20 | INSTALL(TARGETS commotion DESTINATION lib) 21 | INSTALL(FILES commotion.h DESTINATION include) 22 | INSTALL(TARGETS daemon RUNTIME DESTINATION sbin) 23 | INSTALL(TARGETS client RUNTIME DESTINATION bin) 24 | -------------------------------------------------------------------------------- /src/client.c: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file client.c 4 | * @brief commotion - a client to the embedded C daemon 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include "config.h" 38 | #include "debug.h" 39 | #include "util.h" 40 | #include "commotion.h" 41 | 42 | #define INPUT_MAX 255 43 | 44 | /** 45 | * @brief parses command line inputs and packages into a commotion message 46 | * @param argv[] commands input by the user 47 | * @param argc number of commands and flags input 48 | */ 49 | 50 | static co_obj_t * 51 | cli_parse_argv(char *argv[], const int argc) 52 | { 53 | co_obj_t *request = co_request_create(); 54 | if(argc > 0) 55 | { 56 | for(int i = 0; i < argc; i++) 57 | { 58 | CHECK(co_request_append_str(request, argv[i], strlen(argv[i]) + 1), "Failed to add to argument list."); 59 | } 60 | } 61 | return request; 62 | error: 63 | co_free(request); 64 | return NULL; 65 | } 66 | 67 | /** 68 | * @brief checks user input for valid commands 69 | * @param input user input submitted at the command prompt 70 | */ 71 | static co_obj_t * 72 | cli_parse_string(char *input, const size_t ilen) 73 | { 74 | char *saveptr = NULL, *token = NULL; 75 | co_obj_t *request = co_request_create(); 76 | if(input != NULL && ilen > 0) 77 | { 78 | token = strtok_r(input, " ", &saveptr); 79 | DEBUG("Token: %s, Length: %d", token, (int)strlen(token)); 80 | } 81 | while(token != NULL) 82 | { 83 | CHECK(co_request_append_str(request, token, strlen(token) + 1), "Failed to add to argument list."); 84 | DEBUG("Token: %s, Length: %d", token, (int)strlen(token)); 85 | token = strtok_r(NULL, " ", &saveptr); 86 | } 87 | return request; 88 | 89 | error: 90 | co_free(request); 91 | return NULL; 92 | } 93 | 94 | /** 95 | * @brief prints Commotion management shell usage 96 | * @details allows user to specify management socket 97 | */ 98 | static void print_usage() { 99 | printf( 100 | "The Commotion management shell.\n" 101 | "http://commotionwireless.net\n\n" 102 | "Usage: commotion [options]\n" 103 | "\n" 104 | "Options:\n" 105 | " -b, --bind Specify management socket.\n" 106 | " -h, --help Print this usage message.\n" 107 | ); 108 | } 109 | 110 | 111 | int main(int argc, char *argv[]) { 112 | int retval = 1; 113 | int opt = 0; 114 | int opt_index = 0; 115 | char *socket_uri = COMMOTION_MANAGESOCK; 116 | char *method = NULL; 117 | size_t mlen = 0; 118 | co_obj_t *request = NULL, *response = NULL; 119 | 120 | static const char *opt_string = "b:h"; 121 | 122 | static struct option long_opts[] = { 123 | {"bind", required_argument, NULL, 'b'}, 124 | {"help", no_argument, NULL, 'h'} 125 | }; 126 | 127 | opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); 128 | 129 | while(opt != -1) { 130 | switch(opt) { 131 | case 'b': 132 | socket_uri = optarg; 133 | break; 134 | case 'h': 135 | default: 136 | print_usage(); 137 | return 0; 138 | break; 139 | } 140 | opt = getopt_long(argc, argv, opt_string, long_opts, &opt_index); 141 | } 142 | 143 | DEBUG("optind: %d, argc: %d", optind, argc); 144 | co_init(); 145 | co_obj_t *conn = co_connect(socket_uri, strlen(socket_uri) + 1); 146 | CHECK(conn != NULL, "Failed to connect to commotiond at %s\n", socket_uri); 147 | 148 | if(optind < argc) 149 | { 150 | method = argv[optind]; 151 | mlen = strlen(argv[optind]) + 1; 152 | request = cli_parse_argv(argv + optind + 1, argc - optind - 1); 153 | if(co_call(conn, &response, method, mlen, request)) retval = 0; 154 | CHECK(response != NULL, "Invalid response"); 155 | co_response_print(response); 156 | } 157 | else 158 | { 159 | printf("Connected to commotiond at %s\n", socket_uri); 160 | char input[INPUT_MAX]; 161 | char buf[INPUT_MAX]; 162 | memset(input, '\0', sizeof(input)); 163 | int blen = 0; 164 | while(printf("Co$ "), fgets(input, INPUT_MAX, stdin), !feof(stdin)) 165 | { 166 | strstrip(input, buf, INPUT_MAX); 167 | blen = strlen(buf); 168 | if(buf[blen - 1] == '\n') buf[blen - 1] ='\0'; 169 | method = strtok(buf, " "); 170 | mlen = strlen(method) + 1; 171 | if(mlen < 2) method = "help"; 172 | if(blen > mlen) 173 | { 174 | request = cli_parse_string(buf + mlen, blen - mlen); 175 | } 176 | else 177 | { 178 | request = cli_parse_string(NULL, 0); 179 | } 180 | if(co_call(conn, &response, method, mlen, request)) retval = 0; 181 | CHECK(response != NULL, "Invalid response"); 182 | co_free(request); 183 | co_response_print(response); 184 | co_free(response); 185 | } 186 | } 187 | co_shutdown(); 188 | return retval; 189 | error: 190 | co_shutdown(); 191 | return retval; 192 | } 193 | 194 | -------------------------------------------------------------------------------- /src/cmd.c: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file command.c 4 | * @brief a mechanism for registering and controlling display of commands 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include "debug.h" 37 | #include "obj.h" 38 | #include "list.h" 39 | #include "tree.h" 40 | #include "cmd.h" 41 | 42 | static co_obj_t *_cmds = NULL; 43 | 44 | void 45 | co_cmds_shutdown(void) 46 | { 47 | if(_cmds != NULL) co_obj_free(_cmds); 48 | return; 49 | } 50 | 51 | int 52 | co_cmds_init(const size_t index_size) 53 | { 54 | if(_cmds == NULL) 55 | { 56 | if(index_size == 16) 57 | { 58 | CHECK((_cmds = (co_obj_t *)co_tree16_create()) != NULL, "Command tree creation failed."); 59 | } 60 | else if(index_size == 32) 61 | { 62 | CHECK((_cmds = (co_obj_t *)co_tree32_create()) != NULL, "Command tree creation failed."); 63 | } 64 | else SENTINEL("Invalid tree index size."); 65 | } 66 | else DEBUG("Command tree already initialized."); 67 | 68 | return 1; 69 | 70 | error: 71 | co_cmds_shutdown(); 72 | return 0; 73 | } 74 | 75 | static co_obj_t * 76 | _co_cmd_create(const char *name, const size_t nlen, const char *usage, const size_t ulen, const char *desc, const size_t dlen, co_cb_t handler) 77 | { 78 | DEBUG("Creating command %s", name); 79 | co_cmd_t *cmd = h_calloc(1, sizeof(co_cmd_t)); 80 | cmd->exec = handler; 81 | CHECK_MEM(cmd->name = co_str8_create(name, nlen, 0)); 82 | hattach(cmd->name, cmd); 83 | CHECK_MEM(cmd->usage = co_str16_create(usage, ulen, 0)); 84 | hattach(cmd->usage, cmd); 85 | CHECK_MEM(cmd->desc = co_str16_create(desc, dlen, 0)); 86 | hattach(cmd->desc, cmd); 87 | cmd->_len = (sizeof(co_obj_t *) * 3); 88 | cmd->_exttype = _cmd; 89 | cmd->_header._type = _ext8; 90 | cmd->_header._ref = 0; 91 | cmd->_header._flags = 0; 92 | return (co_obj_t *)cmd; 93 | error: 94 | DEBUG("Failed to create command %s.", name); 95 | return NULL; 96 | } 97 | 98 | int 99 | co_cmd_register(const char *name, const size_t nlen, const char *usage, const size_t ulen, const char *desc, const size_t dlen, co_cb_t handler) 100 | { 101 | CHECK(co_tree_insert(_cmds, name, strlen(name), _co_cmd_create(name, nlen, usage, ulen, desc, dlen, handler)), "Failed to register command."); 102 | return 1; 103 | error: 104 | return 0; 105 | } 106 | 107 | 108 | int 109 | co_cmd_exec(co_obj_t *key, co_obj_t **output, co_obj_t *param) 110 | { 111 | char *kstr = NULL; 112 | ssize_t klen = co_obj_data(&kstr, key); 113 | CHECK(klen > 0, "Failed to extract command key"); 114 | co_cmd_t *cmd = (co_cmd_t *)co_tree_find(_cmds, kstr, klen - 1); 115 | 116 | CHECK((cmd != NULL), "No such command!"); 117 | return cmd->exec((co_obj_t *)cmd, output, param); 118 | error: 119 | return 0; 120 | } 121 | 122 | co_obj_t * 123 | co_cmd_usage(co_obj_t *key) 124 | { 125 | char *kstr = NULL; 126 | ssize_t klen = co_obj_data(&kstr, key); 127 | CHECK(klen > 0, "Failed to extract command key"); 128 | co_cmd_t *cmd = (co_cmd_t *)co_tree_find(_cmds, kstr, klen - 1); 129 | 130 | CHECK((cmd != NULL), "No such command!"); 131 | return cmd->usage; 132 | error: 133 | return NULL; 134 | } 135 | 136 | co_obj_t * 137 | co_cmd_desc(co_obj_t *key) 138 | { 139 | char *kstr = NULL; 140 | ssize_t klen = co_obj_data(&kstr, key); 141 | CHECK(klen > 0, "Failed to extract command key"); 142 | co_cmd_t *cmd = (co_cmd_t *)co_tree_find(_cmds, kstr, klen - 1); 143 | 144 | CHECK((cmd != NULL), "No such command!"); 145 | return cmd->desc; 146 | error: 147 | return NULL; 148 | } 149 | 150 | int 151 | co_cmd_hook_str(const char *key, const size_t klen, co_obj_t *cb) 152 | { 153 | co_cmd_t *cmd = (co_cmd_t *)co_tree_find(_cmds, key, klen); 154 | 155 | CHECK((cmd != NULL), "No such command!"); 156 | if(cmd->hooks == NULL) 157 | { 158 | cmd->hooks = co_tree16_create(); 159 | } 160 | CHECK(co_list_append(cmd->hooks, cb), "Failed to add hook to command."); 161 | return 1; 162 | error: 163 | return 0; 164 | } 165 | 166 | int 167 | co_cmd_hook(const co_obj_t *key, co_obj_t *cb) 168 | { 169 | char *kstr = NULL; 170 | ssize_t klen = co_obj_data(&kstr, key); 171 | CHECK(klen > 0, "Failed to extract command key"); 172 | co_cmd_t *cmd = (co_cmd_t *)co_tree_find(_cmds, kstr, klen); 173 | 174 | CHECK((cmd != NULL), "No such command!"); 175 | if(cmd->hooks == NULL) 176 | { 177 | cmd->hooks = co_tree16_create(); 178 | } 179 | CHECK(co_list_append(cmd->hooks, cb), "Failed to add hook to command."); 180 | return 1; 181 | error: 182 | return 0; 183 | } 184 | 185 | int 186 | co_cmd_process(co_iter_t iter, void *context) 187 | { 188 | CHECK(co_tree_process(_cmds, iter, context), "Failed to process commands."); 189 | return 1; 190 | error: 191 | return 0; 192 | } 193 | -------------------------------------------------------------------------------- /src/cmd.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file cmd.h 4 | * @brief a mechanism for registering and controlling display of commands 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #ifndef _CMD_H 34 | #define _CMD_H 35 | 36 | #include 37 | #include 38 | #include 39 | #include "obj.h" 40 | 41 | #define CMD(N) static int cmd_##N(co_obj_t *self, co_obj_t **output, co_obj_t *params) 42 | 43 | #define CMD_REGISTER(N, U, D) co_cmd_register(#N, sizeof(#N), U, sizeof(U), D, sizeof(D), cmd_##N ) 44 | 45 | #define CMD_OUTPUT(K, V) if(*output == NULL) *output = co_tree16_create(); co_tree_insert(*output, K, sizeof(K), V) 46 | 47 | #define HOOK(N) static int hook_##N##(co_obj_t *self, co_obj_t **output, co_obj_t *params) 48 | 49 | #define HOOK_REGISTER(N, C) co_cmd_hook_str(N, sizeof(N), hook_##N) 50 | 51 | typedef struct co_cmd_t co_cmd_t; 52 | 53 | void co_cmds_shutdown(void); 54 | 55 | int co_cmds_init(const size_t index_size); 56 | 57 | /** 58 | * @struct co_cmd_t 59 | * @brief a struct containing all the relevant information for a specific command 60 | */ 61 | struct co_cmd_t { 62 | co_obj_t _header; 63 | uint8_t _exttype; 64 | uint8_t _len; 65 | co_cb_t exec; /**< pointer to the command's function */ 66 | co_obj_t *name; /**< command name */ 67 | co_obj_t *usage; /**< usage syntax */ 68 | co_obj_t *desc; /**< description */ 69 | co_obj_t *hooks; 70 | } __attribute__((packed)); 71 | 72 | int co_cmd_register(const char *name, const size_t nlen, const char *usage, const size_t ulen, const char *desc, const size_t dlen, co_cb_t handler); 73 | 74 | /** 75 | * @brief executes a command by running the function linked to in the command struct 76 | * @param key the name of the command 77 | * @param output return object of command 78 | */ 79 | int co_cmd_exec(co_obj_t *key, co_obj_t **output, co_obj_t *param); 80 | 81 | /** 82 | * @brief returns command usage format 83 | * @param key command name 84 | */ 85 | co_obj_t *co_cmd_usage(co_obj_t *key); 86 | 87 | /** 88 | * @brief returns command description (what the command does) 89 | * @param key the name of the command 90 | */ 91 | co_obj_t *co_cmd_desc(co_obj_t *key); 92 | 93 | /** 94 | * @brief hooks callback function into a command 95 | * @param key the name of the command 96 | * @param cb reference to callback function 97 | */ 98 | int co_cmd_hook(const co_obj_t *key, co_obj_t *cb); 99 | 100 | /** 101 | * @brief hooks callback function into a command 102 | * @param key the name of the command 103 | * @param klen length of key string 104 | * @param cb reference to callback function 105 | */ 106 | int co_cmd_hook_str(const char *key, const size_t klen, co_obj_t *cb); 107 | 108 | /** 109 | * @brief process all registered commands with given iterator 110 | * @param iter iterator function reference 111 | * @param context other parameters passed to iterator 112 | */ 113 | int co_cmd_process(co_iter_t iter, void *context); 114 | #endif 115 | -------------------------------------------------------------------------------- /src/commotion.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file commotion.h 4 | * @brief Client API for the Commotion Daemon 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 12/16/2013 12:00:25 PM 10 | * Compiler gcc/g++ 11 | * Organization The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Josh King 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU Affero General Public License as 18 | * published by the Free Software Foundation, either version 3 of the 19 | * License, or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU Affero General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU Affero General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | 32 | #include 33 | 34 | #ifndef _CONNECT_H 35 | #define _CONNECT_H 36 | 37 | #ifndef CO_OBJ_INTERNAL 38 | typedef void co_obj_t; 39 | #endif 40 | 41 | /** 42 | * @brief initializes API 43 | */ 44 | int co_init(void); 45 | 46 | /** 47 | * @brief shuts down the API 48 | */ 49 | int co_shutdown(void); 50 | 51 | /** 52 | * @brief creates a connection to Commotion daemon at the given URI 53 | * @param uri URI string 54 | * @param ulen length of URI string 55 | */ 56 | co_obj_t *co_connect(const char *uri, const size_t ulen); 57 | 58 | /** 59 | * @brief closes connection to Commotion daemon 60 | * @param connection context object for active connection 61 | */ 62 | int co_disconnect(co_obj_t *connection); 63 | 64 | /** 65 | * @brief create an API request 66 | */ 67 | co_obj_t *co_request_create(void); 68 | 69 | /** 70 | * @brief appends object to request 71 | * @param request request object to append to 72 | * @param object object to append 73 | */ 74 | int co_request_append(co_obj_t *request, co_obj_t *object); 75 | 76 | /** 77 | * @brief appends string to request 78 | * @param request request object to append to 79 | * @param s string to append 80 | * @param slen length of string to append 81 | */ 82 | int co_request_append_str(co_obj_t *request, const char *s, const size_t slen); 83 | 84 | /** 85 | * @brief appends byte array to request 86 | * @param request request object to append to 87 | * @param s array to append 88 | * @param slen length of array to append 89 | */ 90 | int co_request_append_bin(co_obj_t *request, const char *s, const size_t slen); 91 | 92 | /** 93 | * @brief appends int to request 94 | * @param request request object to append to 95 | * @param i integer to append 96 | */ 97 | int co_request_append_int(co_obj_t *request, const int i); 98 | 99 | /** 100 | * @brief appends unsigned int to request 101 | * @param request request object to append to 102 | * @param i integer to append 103 | */ 104 | int co_request_append_uint(co_obj_t *request, const unsigned int i); 105 | 106 | /** 107 | * @brief sense procedure call to daemon 108 | * @param connection context object for connection 109 | * @param response pointer to response buffer 110 | * @param method method name 111 | * @param mlen length of method name 112 | * @param request request object to send 113 | */ 114 | int co_call(co_obj_t *connection, co_obj_t **response, const char *method, const size_t mlen, co_obj_t *request); 115 | 116 | /** 117 | * @brief retrieve object from response 118 | * @param response pointer to response object 119 | * @param key identifier for response element to retrieve 120 | * @param klen length of key name 121 | */ 122 | co_obj_t *co_response_get(co_obj_t *response, const char *key, const size_t klen); 123 | 124 | /** 125 | * @brief retrieve string from response 126 | * @param response pointer to response object 127 | * @param output pointer to output buffer 128 | * @param key identifier for response element to retrieve 129 | * @param klen length of key name 130 | */ 131 | ssize_t co_response_get_str(co_obj_t *response, char **output, const char *key, const size_t klen); 132 | 133 | /** 134 | * @brief retrieve byte array from response 135 | * @param response pointer to response object 136 | * @param output pointer to output buffer 137 | * @param key identifier for response element to retrieve 138 | * @param klen length of key name 139 | */ 140 | ssize_t co_response_get_bin(co_obj_t *response, char **output, const char *key, const size_t klen); 141 | 142 | /** 143 | * @brief retrieve unsigned int from response 144 | * @param response pointer to response object 145 | * @param output pointer to output buffer 146 | * @param key identifier for response element to retrieve 147 | * @param klen length of key name 148 | */ 149 | int co_response_get_uint(co_obj_t *response, unsigned long *output, const char *key, const size_t klen); 150 | 151 | /** 152 | * @brief retrieve signed int from response 153 | * @param response pointer to response object 154 | * @param output pointer to output buffer 155 | * @param key identifier for response element to retrieve 156 | * @param klen length of key name 157 | */ 158 | int co_response_get_int(co_obj_t *response, signed long *output, const char *key, const size_t klen); 159 | 160 | /** 161 | * @brief retrieve bool from response 162 | * @param response pointer to response object 163 | * @param output pointer to output buffer 164 | * @param key identifier for response element to retrieve 165 | * @param klen length of key name 166 | */ 167 | int co_response_get_bool(co_obj_t *response, bool *output, const char *key, const size_t klen); 168 | 169 | /** 170 | * @brief print response object 171 | * @param response pointer to response object 172 | */ 173 | int co_response_print(co_obj_t *response); 174 | 175 | /** 176 | * @brief free API objects 177 | * @param object object to free 178 | */ 179 | void co_free(co_obj_t *object); 180 | #endif 181 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H 2 | #define _CONFIG_H 3 | 4 | #define COMMOTION_VERSION_MAJOR ${COMMOTION_VERSION_MAJOR} 5 | #define COMMOTION_VERSION_MINOR ${COMMOTION_VERSION_MINOR} 6 | #define COMMOTION_VERSION_PATCH ${COMMOTION_VERSION_PATCH} 7 | #define COMMOTION_CONFIGFILE ${COMMOTION_CONFIGFILE} 8 | #define COMMOTION_STATEDIR ${COMMOTION_STATEDIR} 9 | #define COMMOTION_PIDFILE ${COMMOTION_PIDFILE} 10 | #define COMMOTION_MANAGESOCK ${COMMOTION_MANAGESOCK} 11 | #define COMMOTION_PLUGINDIR ${COMMOTION_PLUGINDIR} 12 | #define COMMOTION_PROFILEDIR ${COMMOTION_PROFILEDIR} 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/debug.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file debug.h 4 | * @brief debug macros for the Commotion daemon 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * ------------------------------------------------------------------ 30 | * Copyright (c) 2010, Zed A. Shaw and Mongrel2 Project Contributors. 31 | * All rights reserved. 32 | * 33 | * Redistribution and use in source and binary forms, with or without 34 | * modification, are permitted provided that the following conditions are 35 | * met: 36 | * 37 | * * Redistributions of source code must retain the above copyright 38 | * notice, this list of conditions and the following disclaimer. 39 | * 40 | * * Redistributions in binary form must reproduce the above copyright 41 | * notice, this list of conditions and the following disclaimer in the 42 | * documentation and/or other materials provided with the distribution. 43 | * 44 | * * Neither the name of the Mongrel2 Project, Zed A. Shaw, nor the names 45 | * of its contributors may be used to endorse or promote products 46 | * derived from this software without specific prior written 47 | * permission. 48 | * 49 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 50 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 51 | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 52 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 53 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 54 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 55 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 56 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 57 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 58 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 59 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 | * 61 | * ===================================================================================== 62 | */ 63 | 64 | #ifndef __DEBUG_H__ 65 | #define __DEBUG_H__ 66 | 67 | #include 68 | #include 69 | #include 70 | 71 | #undef LOG 72 | #undef DEBUG 73 | #undef CLEAN_ERRNO 74 | #undef ERROR 75 | #undef WARN 76 | #undef INFO 77 | #undef CHECK 78 | #undef SENTINEL 79 | #undef CHECK_MEM 80 | #undef CHECK_DEBUG 81 | 82 | #ifdef USESYSLOG 83 | #include 84 | #define LOG(M, ...) syslog(M, ##__VA_ARGS__) 85 | #else 86 | #define LOG(M, N, ...) fprintf(stderr, "["M"] " N, ##__VA_ARGS__) 87 | #define LOG_INFO "LOG_INFO" 88 | #define LOG_WARNING "LOG_WARNING" 89 | #define LOG_ERR "LOG_ERR" 90 | #define LOG_DEBUG "LOG_DEBUG" 91 | #endif 92 | 93 | #if defined(NDEBUG) 94 | #define DEBUG(M, ...) 95 | #else 96 | #define DEBUG(M, ...) LOG(LOG_DEBUG, "(%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 97 | #endif 98 | 99 | #define CLEAN_ERRNO() (errno == 0 ? "None" : strerror(errno)) 100 | 101 | #define ERROR(M, ...) LOG(LOG_ERR, "(%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, CLEAN_ERRNO(), ##__VA_ARGS__) 102 | 103 | #define WARN(M, ...) LOG(LOG_WARNING, "(%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, CLEAN_ERRNO(), ##__VA_ARGS__) 104 | 105 | #define INFO(M, ...) LOG(LOG_INFO, "(%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) 106 | 107 | #define CHECK(A, M, ...) do { if(!(A)) { ERROR(M, ##__VA_ARGS__); errno=0; goto error; } } while (0) 108 | 109 | #define SENTINEL(M, ...) { ERROR(M, ##__VA_ARGS__); errno=0; goto error; } 110 | 111 | #define CHECK_MEM(A) CHECK((A), "Out of memory.") 112 | 113 | #define CHECK_DEBUG(A, M, ...) do { if(!(A)) { DEBUG(M, ##__VA_ARGS__); errno=0; goto error; } } while(0) 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /src/extern/align.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of Hierarchical Allocator library. 3 | * Copyright (c) 2004-2011 Alex Pankratov. All rights reserved. 4 | * 5 | * http://swapped.cc/halloc 6 | */ 7 | 8 | /* 9 | * The program is distributed under terms of BSD license. 10 | * You can obtain the copy of the license by visiting: 11 | * 12 | * http://www.opensource.org/licenses/bsd-license.php 13 | */ 14 | 15 | #ifndef _LIBP_ALIGN_H_ 16 | #define _LIBP_ALIGN_H_ 17 | 18 | /* 19 | * a type with the most strict alignment requirements 20 | */ 21 | union max_align 22 | { 23 | char c; 24 | short s; 25 | long l; 26 | int i; 27 | float f; 28 | double d; 29 | void * v; 30 | void (*q)(void); 31 | }; 32 | 33 | typedef union max_align max_align_t; 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /src/extern/halloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of Hierarchical Allocator library. 3 | * Copyright (c) 2004-2011 Alex Pankratov. All rights reserved. 4 | * 5 | * http://swapped.cc/halloc 6 | */ 7 | 8 | /* 9 | * The program is distributed under terms of BSD license. 10 | * You can obtain the copy of the license by visiting: 11 | * 12 | * http://www.opensource.org/licenses/bsd-license.php 13 | */ 14 | 15 | #include /* realloc */ 16 | #include /* memset & co */ 17 | 18 | #include "halloc.h" 19 | #include "align.h" 20 | #include "hlist.h" 21 | 22 | /* 23 | * block control header 24 | */ 25 | typedef struct hblock 26 | { 27 | #ifndef NDEBUG 28 | #define HH_MAGIC 0x20040518L 29 | long magic; 30 | #endif 31 | hlist_item_t siblings; /* 2 pointers */ 32 | hlist_head_t children; /* 1 pointer */ 33 | max_align_t data[1]; /* not allocated, see below */ 34 | 35 | } hblock_t; 36 | 37 | #define sizeof_hblock offsetof(hblock_t, data) 38 | 39 | /* 40 | * 41 | */ 42 | realloc_t halloc_allocator = NULL; 43 | 44 | #define allocator halloc_allocator 45 | 46 | /* 47 | * static methods 48 | */ 49 | static void _set_allocator(void); 50 | static void * _realloc(void * ptr, size_t n); 51 | 52 | static int _relate(hblock_t * b, hblock_t * p); 53 | static void _free_children(hblock_t * p); 54 | 55 | /* 56 | * Core API 57 | */ 58 | void * halloc(void * ptr, size_t len) 59 | { 60 | hblock_t * p; 61 | 62 | /* set up default allocator */ 63 | if (! allocator) 64 | { 65 | _set_allocator(); 66 | assert(allocator); 67 | } 68 | 69 | /* calloc */ 70 | if (! ptr) 71 | { 72 | if (! len) 73 | return NULL; 74 | 75 | p = allocator(0, len + sizeof_hblock); 76 | if (! p) 77 | return NULL; 78 | #ifndef NDEBUG 79 | p->magic = HH_MAGIC; 80 | #endif 81 | hlist_init(&p->children); 82 | hlist_init_item(&p->siblings); 83 | 84 | return p->data; 85 | } 86 | 87 | p = structof(ptr, hblock_t, data); 88 | assert(p->magic == HH_MAGIC); 89 | 90 | /* realloc */ 91 | if (len) 92 | { 93 | p = allocator(p, len + sizeof_hblock); 94 | if (! p) 95 | return NULL; 96 | 97 | hlist_relink(&p->siblings); 98 | hlist_relink_head(&p->children); 99 | 100 | return p->data; 101 | } 102 | 103 | /* free */ 104 | _free_children(p); 105 | hlist_del(&p->siblings); 106 | allocator(p, 0); 107 | 108 | return NULL; 109 | } 110 | 111 | void hattach(void * block, void * parent) 112 | { 113 | hblock_t * b, * p; 114 | 115 | if (! block) 116 | { 117 | assert(! parent); 118 | return; 119 | } 120 | 121 | /* detach */ 122 | b = structof(block, hblock_t, data); 123 | assert(b->magic == HH_MAGIC); 124 | 125 | hlist_del(&b->siblings); 126 | 127 | if (! parent) 128 | return; 129 | 130 | /* attach */ 131 | p = structof(parent, hblock_t, data); 132 | assert(p->magic == HH_MAGIC); 133 | 134 | /* sanity checks */ 135 | assert(b != p); /* trivial */ 136 | assert(! _relate(p, b)); /* heavy ! */ 137 | 138 | hlist_add(&p->children, &b->siblings); 139 | } 140 | 141 | /* 142 | * malloc/free api 143 | */ 144 | void * h_malloc(size_t len) 145 | { 146 | return halloc(0, len); 147 | } 148 | 149 | void * h_calloc(size_t n, size_t len) 150 | { 151 | void * ptr = halloc(0, len*=n); 152 | return ptr ? memset(ptr, 0, len) : NULL; 153 | } 154 | 155 | void * h_realloc(void * ptr, size_t len) 156 | { 157 | return halloc(ptr, len); 158 | } 159 | 160 | void h_free(void * ptr) 161 | { 162 | halloc(ptr, 0); 163 | } 164 | 165 | char * h_strdup(const char * str) 166 | { 167 | size_t len = strlen(str); 168 | char * ptr = halloc(0, len + 1); 169 | return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL; 170 | } 171 | 172 | /* 173 | * static stuff 174 | */ 175 | static void _set_allocator(void) 176 | { 177 | void * p; 178 | assert(! allocator); 179 | 180 | /* 181 | * the purpose of the test below is to check the behaviour 182 | * of realloc(ptr, 0), which is defined in the standard 183 | * as an implementation-specific. if it returns zero, 184 | * then it's equivalent to free(). it can however return 185 | * non-zero, in which case it cannot be used for freeing 186 | * memory blocks and we'll need to supply our own version 187 | * 188 | * Thanks to Stan Tobias for pointing this tricky part out. 189 | */ 190 | allocator = realloc; 191 | if (! (p = malloc(1))) 192 | /* hmm */ 193 | return; 194 | 195 | if ((p = realloc(p, 0))) 196 | { 197 | /* realloc cannot be used as free() */ 198 | allocator = _realloc; 199 | free(p); 200 | } 201 | } 202 | 203 | static void * _realloc(void * ptr, size_t n) 204 | { 205 | /* 206 | * free'ing realloc() 207 | */ 208 | if (n) 209 | return realloc(ptr, n); 210 | free(ptr); 211 | return NULL; 212 | } 213 | 214 | static int _relate(hblock_t * b, hblock_t * p) 215 | { 216 | hlist_item_t * i; 217 | 218 | if (!b || !p) 219 | return 0; 220 | 221 | /* 222 | * since there is no 'parent' pointer, which would've allowed 223 | * O(log(n)) upward traversal, the check must use O(n) downward 224 | * iteration of the entire hierarchy; and this can be VERY SLOW 225 | */ 226 | hlist_for_each(i, &p->children) 227 | { 228 | hblock_t * q = structof(i, hblock_t, siblings); 229 | if (q == b || _relate(b, q)) 230 | return 1; 231 | } 232 | return 0; 233 | } 234 | 235 | static void _free_children(hblock_t * p) 236 | { 237 | hlist_item_t * i, * tmp; 238 | 239 | #ifndef NDEBUG 240 | /* 241 | * this catches loops in hierarchy with almost zero 242 | * overhead (compared to _relate() running time) 243 | */ 244 | assert(p && p->magic == HH_MAGIC); 245 | p->magic = 0; 246 | #endif 247 | hlist_for_each_safe(i, tmp, &p->children) 248 | { 249 | hblock_t * q = structof(i, hblock_t, siblings); 250 | _free_children(q); 251 | allocator(q, 0); 252 | } 253 | } 254 | 255 | -------------------------------------------------------------------------------- /src/extern/halloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of Hierarchical Allocator library. 3 | * Copyright (c) 2004-2011 Alex Pankratov. All rights reserved. 4 | * 5 | * http://swapped.cc/halloc 6 | */ 7 | 8 | /* 9 | * The program is distributed under terms of BSD license. 10 | * You can obtain the copy of the license by visiting: 11 | * 12 | * http://www.opensource.org/licenses/bsd-license.php 13 | */ 14 | 15 | #ifndef _LIBP_HALLOC_H_ 16 | #define _LIBP_HALLOC_H_ 17 | 18 | #include /* size_t */ 19 | 20 | /* 21 | * Core API 22 | */ 23 | void * halloc (void * block, size_t len); 24 | void hattach(void * block, void * parent); 25 | 26 | /* 27 | * standard malloc/free api 28 | */ 29 | void * h_malloc (size_t len); 30 | void * h_calloc (size_t n, size_t len); 31 | void * h_realloc(void * p, size_t len); 32 | void h_free (void * p); 33 | char * h_strdup (const char * str); 34 | 35 | /* 36 | * the underlying allocator 37 | */ 38 | typedef void * (* realloc_t)(void * ptr, size_t len); 39 | 40 | extern realloc_t halloc_allocator; 41 | 42 | #endif 43 | 44 | -------------------------------------------------------------------------------- /src/extern/hlist.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of Hierarchical Allocator library. 3 | * Copyright (c) 2004-2011 Alex Pankratov. All rights reserved. 4 | * 5 | * http://swapped.cc/halloc 6 | */ 7 | 8 | /* 9 | * The program is distributed under terms of BSD license. 10 | * You can obtain the copy of the license by visiting: 11 | * 12 | * http://www.opensource.org/licenses/bsd-license.php 13 | */ 14 | 15 | #ifndef _LIBP_HLIST_H_ 16 | #define _LIBP_HLIST_H_ 17 | 18 | #include 19 | #include "macros.h" /* static_inline */ 20 | 21 | /* 22 | * weak double-linked list w/ tail sentinel 23 | */ 24 | typedef struct hlist_head hlist_head_t; 25 | typedef struct hlist_item hlist_item_t; 26 | 27 | /* 28 | * 29 | */ 30 | struct hlist_head 31 | { 32 | hlist_item_t * next; 33 | }; 34 | 35 | struct hlist_item 36 | { 37 | hlist_item_t * next; 38 | hlist_item_t ** prev; 39 | }; 40 | 41 | /* 42 | * shared tail sentinel 43 | */ 44 | struct hlist_item hlist_null; 45 | 46 | /* 47 | * 48 | */ 49 | #define __hlist_init(h) { &hlist_null } 50 | #define __hlist_init_item(i) { &hlist_null, &(i).next } 51 | 52 | static_inline void hlist_init(hlist_head_t * h); 53 | static_inline void hlist_init_item(hlist_item_t * i); 54 | 55 | /* static_inline void hlist_purge(hlist_head_t * h); */ 56 | 57 | /* static_inline bool_t hlist_empty(const hlist_head_t * h); */ 58 | 59 | /* static_inline hlist_item_t * hlist_head(const hlist_head_t * h); */ 60 | 61 | /* static_inline hlist_item_t * hlist_next(const hlist_item_t * i); */ 62 | /* static_inline hlist_item_t * hlist_prev(const hlist_item_t * i, 63 | const hlist_head_t * h); */ 64 | 65 | static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i); 66 | 67 | /* static_inline void hlist_add_prev(hlist_item_t * l, hlist_item_t * i); */ 68 | /* static_inline void hlist_add_next(hlist_item_t * l, hlist_item_t * i); */ 69 | 70 | static_inline void hlist_del(hlist_item_t * i); 71 | 72 | static_inline void hlist_relink(hlist_item_t * i); 73 | static_inline void hlist_relink_head(hlist_head_t * h); 74 | 75 | #define hlist_for_each(i, h) \ 76 | for (i = (h)->next; i != &hlist_null; i = i->next) 77 | 78 | #define hlist_for_each_safe(i, tmp, h) \ 79 | for (i = (h)->next, tmp = i->next; \ 80 | i!= &hlist_null; \ 81 | i = tmp, tmp = i->next) 82 | 83 | /* 84 | * static 85 | */ 86 | static_inline void hlist_init(hlist_head_t * h) 87 | { 88 | assert(h); 89 | h->next = &hlist_null; 90 | } 91 | 92 | static_inline void hlist_init_item(hlist_item_t * i) 93 | { 94 | assert(i); 95 | i->prev = &i->next; 96 | i->next = &hlist_null; 97 | } 98 | 99 | static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i) 100 | { 101 | hlist_item_t * next; 102 | assert(h && i); 103 | 104 | next = i->next = h->next; 105 | next->prev = &i->next; 106 | h->next = i; 107 | i->prev = &h->next; 108 | } 109 | 110 | static_inline void hlist_del(hlist_item_t * i) 111 | { 112 | hlist_item_t * next; 113 | assert(i); 114 | 115 | next = i->next; 116 | next->prev = i->prev; 117 | *i->prev = next; 118 | 119 | hlist_init_item(i); 120 | } 121 | 122 | static_inline void hlist_relink(hlist_item_t * i) 123 | { 124 | assert(i); 125 | *i->prev = i; 126 | i->next->prev = &i->next; 127 | } 128 | 129 | static_inline void hlist_relink_head(hlist_head_t * h) 130 | { 131 | assert(h); 132 | h->next->prev = &h->next; 133 | } 134 | 135 | #endif 136 | 137 | -------------------------------------------------------------------------------- /src/extern/jsmn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "jsmn.h" 4 | 5 | /** 6 | * Allocates a fresh unused token from the token pull. 7 | */ 8 | static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, 9 | jsmntok_t *tokens, size_t num_tokens) { 10 | jsmntok_t *tok; 11 | if (parser->toknext >= num_tokens) { 12 | return NULL; 13 | } 14 | tok = &tokens[parser->toknext++]; 15 | tok->start = tok->end = -1; 16 | tok->size = 0; 17 | #ifdef JSMN_PARENT_LINKS 18 | tok->parent = -1; 19 | #endif 20 | return tok; 21 | } 22 | 23 | /** 24 | * Fills token type and boundaries. 25 | */ 26 | static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type, 27 | int start, int end) { 28 | token->type = type; 29 | token->start = start; 30 | token->end = end; 31 | token->size = 0; 32 | } 33 | 34 | /** 35 | * Fills next available token with JSON primitive. 36 | */ 37 | static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js, 38 | jsmntok_t *tokens, size_t num_tokens) { 39 | jsmntok_t *token; 40 | int start; 41 | 42 | start = parser->pos; 43 | 44 | for (; js[parser->pos] != '\0'; parser->pos++) { 45 | switch (js[parser->pos]) { 46 | #ifndef JSMN_STRICT 47 | /* In strict mode primitive must be followed by "," or "}" or "]" */ 48 | case ':': 49 | #endif 50 | case '\t' : case '\r' : case '\n' : case ' ' : 51 | case ',' : case ']' : case '}' : 52 | goto found; 53 | } 54 | if (js[parser->pos] < 32 || js[parser->pos] >= 127) { 55 | parser->pos = start; 56 | return JSMN_ERROR_INVAL; 57 | } 58 | } 59 | #ifdef JSMN_STRICT 60 | /* In strict mode primitive must be followed by a comma/object/array */ 61 | parser->pos = start; 62 | return JSMN_ERROR_PART; 63 | #endif 64 | 65 | found: 66 | token = jsmn_alloc_token(parser, tokens, num_tokens); 67 | if (token == NULL) { 68 | parser->pos = start; 69 | return JSMN_ERROR_NOMEM; 70 | } 71 | jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); 72 | #ifdef JSMN_PARENT_LINKS 73 | token->parent = parser->toksuper; 74 | #endif 75 | parser->pos--; 76 | return JSMN_SUCCESS; 77 | } 78 | 79 | /** 80 | * Filsl next token with JSON string. 81 | */ 82 | static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js, 83 | jsmntok_t *tokens, size_t num_tokens) { 84 | jsmntok_t *token; 85 | 86 | int start = parser->pos; 87 | 88 | parser->pos++; 89 | 90 | /* Skip starting quote */ 91 | for (; js[parser->pos] != '\0'; parser->pos++) { 92 | char c = js[parser->pos]; 93 | 94 | /* Quote: end of string */ 95 | if (c == '\"') { 96 | token = jsmn_alloc_token(parser, tokens, num_tokens); 97 | if (token == NULL) { 98 | parser->pos = start; 99 | return JSMN_ERROR_NOMEM; 100 | } 101 | jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos); 102 | #ifdef JSMN_PARENT_LINKS 103 | token->parent = parser->toksuper; 104 | #endif 105 | return JSMN_SUCCESS; 106 | } 107 | 108 | /* Backslash: Quoted symbol expected */ 109 | if (c == '\\') { 110 | parser->pos++; 111 | switch (js[parser->pos]) { 112 | /* Allowed escaped symbols */ 113 | case '\"': case '/' : case '\\' : case 'b' : 114 | case 'f' : case 'r' : case 'n' : case 't' : 115 | break; 116 | /* Allows escaped symbol \uXXXX */ 117 | case 'u': 118 | /* TODO */ 119 | break; 120 | /* Unexpected symbol */ 121 | default: 122 | parser->pos = start; 123 | return JSMN_ERROR_INVAL; 124 | } 125 | } 126 | } 127 | parser->pos = start; 128 | return JSMN_ERROR_PART; 129 | } 130 | 131 | /** 132 | * Parse JSON string and fill tokens. 133 | */ 134 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, jsmntok_t *tokens, 135 | unsigned int num_tokens) { 136 | jsmnerr_t r; 137 | int i; 138 | jsmntok_t *token; 139 | 140 | for (; js[parser->pos] != '\0'; parser->pos++) { 141 | char c; 142 | jsmntype_t type; 143 | 144 | c = js[parser->pos]; 145 | switch (c) { 146 | case '{': case '[': 147 | token = jsmn_alloc_token(parser, tokens, num_tokens); 148 | if (token == NULL) 149 | return JSMN_ERROR_NOMEM; 150 | if (parser->toksuper != -1) { 151 | tokens[parser->toksuper].size++; 152 | #ifdef JSMN_PARENT_LINKS 153 | token->parent = parser->toksuper; 154 | #endif 155 | } 156 | token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); 157 | token->start = parser->pos; 158 | parser->toksuper = parser->toknext - 1; 159 | break; 160 | case '}': case ']': 161 | type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); 162 | #ifdef JSMN_PARENT_LINKS 163 | if (parser->toknext < 1) { 164 | return JSMN_ERROR_INVAL; 165 | } 166 | token = &tokens[parser->toknext - 1]; 167 | for (;;) { 168 | if (token->start != -1 && token->end == -1) { 169 | if (token->type != type) { 170 | return JSMN_ERROR_INVAL; 171 | } 172 | token->end = parser->pos + 1; 173 | parser->toksuper = token->parent; 174 | break; 175 | } 176 | if (token->parent == -1) { 177 | break; 178 | } 179 | token = &tokens[token->parent]; 180 | } 181 | #else 182 | for (i = parser->toknext - 1; i >= 0; i--) { 183 | token = &tokens[i]; 184 | if (token->start != -1 && token->end == -1) { 185 | if (token->type != type) { 186 | return JSMN_ERROR_INVAL; 187 | } 188 | parser->toksuper = -1; 189 | token->end = parser->pos + 1; 190 | break; 191 | } 192 | } 193 | /* Error if unmatched closing bracket */ 194 | if (i == -1) return JSMN_ERROR_INVAL; 195 | for (; i >= 0; i--) { 196 | token = &tokens[i]; 197 | if (token->start != -1 && token->end == -1) { 198 | parser->toksuper = i; 199 | break; 200 | } 201 | } 202 | #endif 203 | break; 204 | case '\"': 205 | r = jsmn_parse_string(parser, js, tokens, num_tokens); 206 | if (r < 0) return r; 207 | if (parser->toksuper != -1) 208 | tokens[parser->toksuper].size++; 209 | break; 210 | case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ': 211 | break; 212 | #ifdef JSMN_STRICT 213 | /* In strict mode primitives are: numbers and booleans */ 214 | case '-': case '0': case '1' : case '2': case '3' : case '4': 215 | case '5': case '6': case '7' : case '8': case '9': 216 | case 't': case 'f': case 'n' : 217 | #else 218 | /* In non-strict mode every unquoted value is a primitive */ 219 | default: 220 | #endif 221 | r = jsmn_parse_primitive(parser, js, tokens, num_tokens); 222 | if (r < 0) return r; 223 | if (parser->toksuper != -1) 224 | tokens[parser->toksuper].size++; 225 | break; 226 | 227 | #ifdef JSMN_STRICT 228 | /* Unexpected char in strict mode */ 229 | default: 230 | return JSMN_ERROR_INVAL; 231 | #endif 232 | 233 | } 234 | } 235 | 236 | for (i = parser->toknext - 1; i >= 0; i--) { 237 | /* Unmatched opened object or array */ 238 | if (tokens[i].start != -1 && tokens[i].end == -1) { 239 | return JSMN_ERROR_PART; 240 | } 241 | } 242 | 243 | return JSMN_SUCCESS; 244 | } 245 | 246 | /** 247 | * Creates a new parser based over a given buffer with an array of tokens 248 | * available. 249 | */ 250 | void jsmn_init(jsmn_parser *parser) { 251 | parser->pos = 0; 252 | parser->toknext = 0; 253 | parser->toksuper = -1; 254 | } 255 | 256 | -------------------------------------------------------------------------------- /src/extern/jsmn.h: -------------------------------------------------------------------------------- 1 | #ifndef __JSMN_H_ 2 | #define __JSMN_H_ 3 | 4 | /** 5 | * JSON type identifier. Basic types are: 6 | * o Object 7 | * o Array 8 | * o String 9 | * o Other primitive: number, boolean (true/false) or null 10 | */ 11 | typedef enum { 12 | JSMN_PRIMITIVE = 0, 13 | JSMN_OBJECT = 1, 14 | JSMN_ARRAY = 2, 15 | JSMN_STRING = 3 16 | } jsmntype_t; 17 | 18 | typedef enum { 19 | /* Not enough tokens were provided */ 20 | JSMN_ERROR_NOMEM = -1, 21 | /* Invalid character inside JSON string */ 22 | JSMN_ERROR_INVAL = -2, 23 | /* The string is not a full JSON packet, more bytes expected */ 24 | JSMN_ERROR_PART = -3, 25 | /* Everything was fine */ 26 | JSMN_SUCCESS = 0 27 | } jsmnerr_t; 28 | 29 | /** 30 | * JSON token description. 31 | * @param type type (object, array, string etc.) 32 | * @param start start position in JSON data string 33 | * @param end end position in JSON data string 34 | */ 35 | typedef struct { 36 | jsmntype_t type; 37 | int start; 38 | int end; 39 | int size; 40 | #ifdef JSMN_PARENT_LINKS 41 | int parent; 42 | #endif 43 | } jsmntok_t; 44 | 45 | /** 46 | * JSON parser. Contains an array of token blocks available. Also stores 47 | * the string being parsed now and current position in that string 48 | */ 49 | typedef struct { 50 | unsigned int pos; /* offset in the JSON string */ 51 | int toknext; /* next token to allocate */ 52 | int toksuper; /* superior token node, e.g parent object or array */ 53 | } jsmn_parser; 54 | 55 | /** 56 | * Create JSON parser over an array of tokens 57 | */ 58 | void jsmn_init(jsmn_parser *parser); 59 | 60 | /** 61 | * Run JSON parser. It parses a JSON data string into and array of tokens, each describing 62 | * a single JSON object. 63 | */ 64 | jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, 65 | jsmntok_t *tokens, unsigned int num_tokens); 66 | 67 | #endif /* __JSMN_H_ */ 68 | -------------------------------------------------------------------------------- /src/extern/macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is a part of Hierarchical Allocator library. 3 | * Copyright (c) 2004-2011 Alex Pankratov. All rights reserved. 4 | * 5 | * http://swapped.cc/halloc 6 | */ 7 | 8 | /* 9 | * The program is distributed under terms of BSD license. 10 | * You can obtain the copy of the license by visiting: 11 | * 12 | * http://www.opensource.org/licenses/bsd-license.php 13 | */ 14 | 15 | #ifndef _LIBP_MACROS_H_ 16 | #define _LIBP_MACROS_H_ 17 | 18 | #include /* offsetof */ 19 | 20 | /* 21 | restore pointer to the structure by a pointer to its field 22 | */ 23 | #define structof(p,t,f) ((t*)(- offsetof(t,f) + (void*)(p))) 24 | 25 | /* 26 | * redefine for the target compiler 27 | */ 28 | #define static_inline static __inline__ 29 | 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /src/extern/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc. 3 | * MD5 Message-Digest Algorithm (RFC 1321). 4 | * 5 | * Homepage: 6 | * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5 7 | * 8 | * Author: 9 | * Alexander Peslyak, better known as Solar Designer 10 | * 11 | * This software was written by Alexander Peslyak in 2001. No copyright is 12 | * claimed, and the software is hereby placed in the public domain. 13 | * In case this attempt to disclaim copyright and place the software in the 14 | * public domain is deemed null and void, then the software is 15 | * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the 16 | * general public under the following terms: 17 | * 18 | * Redistribution and use in source and binary forms, with or without 19 | * modification, are permitted. 20 | * 21 | * There's ABSOLUTELY NO WARRANTY, express or implied. 22 | * 23 | * See md5.c for more information. 24 | */ 25 | 26 | #ifdef HAVE_OPENSSL 27 | #include 28 | #elif !defined(_MD5_H) 29 | #define _MD5_H 30 | 31 | /* Any 32-bit or wider unsigned integer data type will do */ 32 | typedef unsigned int MD5_u32plus; 33 | 34 | typedef struct { 35 | MD5_u32plus lo, hi; 36 | MD5_u32plus a, b, c, d; 37 | unsigned char buffer[64]; 38 | MD5_u32plus block[16]; 39 | } MD5_CTX; 40 | 41 | extern void MD5_Init(MD5_CTX *ctx); 42 | extern void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size); 43 | extern void MD5_Final(unsigned char *result, MD5_CTX *ctx); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/extern/wpa_ctrl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Modifed version of src/common/wpa_ctrl.c from wpa_supplicant, discarding 3 | * all code paths except for CONFIG_CTRL_IFACE_UNIX. Define strlcpy inline, 4 | * it is not provided by GNU libc. 5 | * Copyright (c) 2008, Kel Modderman 6 | * 7 | * wpa_supplicant/hostapd control interface library 8 | * Copyright (c) 2004-2007, Jouni Malinen 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License version 2 as 12 | * published by the Free Software Foundation. 13 | * 14 | * Alternatively, this software may be distributed under the terms of BSD 15 | * license. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "wpa_ctrl.h" 30 | #include "../util.h" 31 | 32 | /** 33 | * strlcpy - Copy a string with size bound and NUL-termination 34 | * @dest: Destination 35 | * @src: Source 36 | * @siz: Size of the target buffer 37 | * Returns: Total length of the target string (length of src) (not including 38 | * NUL-termination) 39 | * 40 | * This function matches in behavior with the strlcpy(3) function in OpenBSD. 41 | */ 42 | //size_t strlcpy(char *dest, const char *src, size_t siz) 43 | //{ 44 | // const char *s = src; 45 | // size_t left = siz; 46 | // 47 | // if (left) { 48 | // /* Copy string up to the maximum size of the dest buffer */ 49 | // while (--left != 0) { 50 | // if ((*dest++ = *s++) == '\0') 51 | // break; 52 | // } 53 | // } 54 | // 55 | // if (left == 0) { 56 | // /* Not enough room for the string; force NUL-termination */ 57 | // if (siz != 0) 58 | // *dest = '\0'; 59 | // while (*s++) 60 | // ; /* determine total src string length */ 61 | // } 62 | // 63 | // return s - src - 1; 64 | //} 65 | // 66 | 67 | /** 68 | * struct wpa_ctrl - Internal structure for control interface library 69 | * 70 | * This structure is used by the wpa_supplicant/hostapd control interface 71 | * library to store internal data. Programs using the library should not touch 72 | * this data directly. They can only use the pointer to the data structure as 73 | * an identifier for the control interface connection and use this as one of 74 | * the arguments for most of the control interface library functions. 75 | */ 76 | struct wpa_ctrl { 77 | int s; 78 | struct sockaddr_un local; 79 | struct sockaddr_un dest; 80 | }; 81 | 82 | 83 | struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path) 84 | { 85 | struct wpa_ctrl *ctrl; 86 | static int counter = 0; 87 | int ret; 88 | size_t res; 89 | 90 | ctrl = malloc(sizeof(*ctrl)); 91 | if (ctrl == NULL) 92 | return NULL; 93 | memset(ctrl, 0, sizeof(*ctrl)); 94 | 95 | ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0); 96 | if (ctrl->s < 0) { 97 | free(ctrl); 98 | return NULL; 99 | } 100 | 101 | ctrl->local.sun_family = AF_UNIX; 102 | ret = snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path), 103 | "/tmp/wpa_ctrl_%d-%d", getpid(), counter++); 104 | if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) { 105 | close(ctrl->s); 106 | free(ctrl); 107 | return NULL; 108 | } 109 | if (bind(ctrl->s, (struct sockaddr *) &ctrl->local, 110 | sizeof(ctrl->local)) < 0) { 111 | close(ctrl->s); 112 | free(ctrl); 113 | return NULL; 114 | } 115 | 116 | ctrl->dest.sun_family = AF_UNIX; 117 | res = strlcpy(ctrl->dest.sun_path, ctrl_path, 118 | sizeof(ctrl->dest.sun_path)); 119 | if (res >= sizeof(ctrl->dest.sun_path)) { 120 | close(ctrl->s); 121 | free(ctrl); 122 | return NULL; 123 | } 124 | if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest, 125 | sizeof(ctrl->dest)) < 0) { 126 | close(ctrl->s); 127 | unlink(ctrl->local.sun_path); 128 | free(ctrl); 129 | return NULL; 130 | } 131 | 132 | return ctrl; 133 | } 134 | 135 | 136 | void wpa_ctrl_close(struct wpa_ctrl *ctrl) 137 | { 138 | unlink(ctrl->local.sun_path); 139 | close(ctrl->s); 140 | free(ctrl); 141 | } 142 | 143 | 144 | int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 145 | char *reply, size_t *reply_len, 146 | void (*msg_cb)(char *msg, size_t len)) 147 | { 148 | struct timeval tv; 149 | int res; 150 | fd_set rfds; 151 | const char *_cmd; 152 | char *cmd_buf = NULL; 153 | size_t _cmd_len; 154 | 155 | { 156 | _cmd = cmd; 157 | _cmd_len = cmd_len; 158 | } 159 | 160 | if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) { 161 | free(cmd_buf); 162 | return -1; 163 | } 164 | free(cmd_buf); 165 | 166 | for (;;) { 167 | tv.tv_sec = 2; 168 | tv.tv_usec = 0; 169 | FD_ZERO(&rfds); 170 | FD_SET(ctrl->s, &rfds); 171 | res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 172 | if (FD_ISSET(ctrl->s, &rfds)) { 173 | res = recv(ctrl->s, reply, *reply_len, 0); 174 | if (res < 0) 175 | return res; 176 | if (res > 0 && reply[0] == '<') { 177 | /* This is an unsolicited message from 178 | * wpa_supplicant, not the reply to the 179 | * request. Use msg_cb to report this to the 180 | * caller. */ 181 | if (msg_cb) { 182 | /* Make sure the message is nul 183 | * terminated. */ 184 | if ((size_t) res == *reply_len) 185 | res = (*reply_len) - 1; 186 | reply[res] = '\0'; 187 | msg_cb(reply, res); 188 | } 189 | continue; 190 | } 191 | *reply_len = res; 192 | break; 193 | } else { 194 | return -2; 195 | } 196 | } 197 | return 0; 198 | } 199 | 200 | 201 | static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach) 202 | { 203 | char buf[10]; 204 | int ret; 205 | size_t len = 10; 206 | 207 | ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6, 208 | buf, &len, NULL); 209 | if (ret < 0) 210 | return ret; 211 | if (len == 3 && memcmp(buf, "OK\n", 3) == 0) 212 | return 0; 213 | return -1; 214 | } 215 | 216 | 217 | int wpa_ctrl_attach(struct wpa_ctrl *ctrl) 218 | { 219 | return wpa_ctrl_attach_helper(ctrl, 1); 220 | } 221 | 222 | 223 | int wpa_ctrl_detach(struct wpa_ctrl *ctrl) 224 | { 225 | return wpa_ctrl_attach_helper(ctrl, 0); 226 | } 227 | 228 | 229 | int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len) 230 | { 231 | int res; 232 | 233 | res = recv(ctrl->s, reply, *reply_len, 0); 234 | if (res < 0) 235 | return res; 236 | *reply_len = res; 237 | return 0; 238 | } 239 | 240 | 241 | int wpa_ctrl_pending(struct wpa_ctrl *ctrl) 242 | { 243 | struct timeval tv; 244 | fd_set rfds; 245 | tv.tv_sec = 0; 246 | tv.tv_usec = 0; 247 | FD_ZERO(&rfds); 248 | FD_SET(ctrl->s, &rfds); 249 | select(ctrl->s + 1, &rfds, NULL, NULL, &tv); 250 | return FD_ISSET(ctrl->s, &rfds); 251 | } 252 | 253 | 254 | int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl) 255 | { 256 | return ctrl->s; 257 | } 258 | -------------------------------------------------------------------------------- /src/extern/wpa_ctrl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Unmodifed version of src/common/wpa_ctrl.h from wpa_supplicant. 3 | * 4 | * wpa_supplicant/hostapd control interface library 5 | * Copyright (c) 2004-2006, Jouni Malinen 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU General Public License version 2 as 9 | * published by the Free Software Foundation. 10 | * 11 | * Alternatively, this software may be distributed under the terms of BSD 12 | * license. 13 | */ 14 | 15 | #ifndef WPA_CTRL_H 16 | #define WPA_CTRL_H 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | /* wpa_supplicant control interface - fixed message prefixes */ 23 | 24 | /** Interactive request for identity/password/pin */ 25 | #define WPA_CTRL_REQ "CTRL-REQ-" 26 | 27 | /** Response to identity/password/pin request */ 28 | #define WPA_CTRL_RSP "CTRL-RSP-" 29 | 30 | /* Event messages with fixed prefix */ 31 | /** Authentication completed successfully and data connection enabled */ 32 | #define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " 33 | /** Disconnected, data connection is not available */ 34 | #define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " 35 | /** wpa_supplicant is exiting */ 36 | #define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " 37 | /** Password change was completed successfully */ 38 | #define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " 39 | /** EAP-Request/Notification received */ 40 | #define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " 41 | /** EAP authentication started (EAP-Request/Identity received) */ 42 | #define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " 43 | /** EAP method selected */ 44 | #define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " 45 | /** EAP authentication completed successfully */ 46 | #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " 47 | /** EAP authentication failed (EAP-Failure received) */ 48 | #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " 49 | /** New scan results available */ 50 | #define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " 51 | 52 | 53 | /* wpa_supplicant/hostapd control interface access */ 54 | 55 | /** 56 | * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd 57 | * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. 58 | * Returns: Pointer to abstract control interface data or %NULL on failure 59 | * 60 | * This function is used to open a control interface to wpa_supplicant/hostapd. 61 | * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path 62 | * is configured in wpa_supplicant/hostapd and other programs using the control 63 | * interface need to use matching path configuration. 64 | */ 65 | struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); 66 | 67 | 68 | /** 69 | * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd 70 | * @ctrl: Control interface data from wpa_ctrl_open() 71 | * 72 | * This function is used to close a control interface. 73 | */ 74 | void wpa_ctrl_close(struct wpa_ctrl *ctrl); 75 | 76 | 77 | /** 78 | * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd 79 | * @ctrl: Control interface data from wpa_ctrl_open() 80 | * @cmd: Command; usually, ASCII text, e.g., "PING" 81 | * @cmd_len: Length of the cmd in bytes 82 | * @reply: Buffer for the response 83 | * @reply_len: Reply buffer length 84 | * @msg_cb: Callback function for unsolicited messages or %NULL if not used 85 | * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout 86 | * 87 | * This function is used to send commands to wpa_supplicant/hostapd. Received 88 | * response will be written to reply and reply_len is set to the actual length 89 | * of the reply. This function will block for up to two seconds while waiting 90 | * for the reply. If unsolicited messages are received, the blocking time may 91 | * be longer. 92 | * 93 | * msg_cb can be used to register a callback function that will be called for 94 | * unsolicited messages received while waiting for the command response. These 95 | * messages may be received if wpa_ctrl_request() is called at the same time as 96 | * wpa_supplicant/hostapd is sending such a message. This can happen only if 97 | * the program has used wpa_ctrl_attach() to register itself as a monitor for 98 | * event messages. Alternatively to msg_cb, programs can register two control 99 | * interface connections and use one of them for commands and the other one for 100 | * receiving event messages, in other words, call wpa_ctrl_attach() only for 101 | * the control interface connection that will be used for event messages. 102 | */ 103 | int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, 104 | char *reply, size_t *reply_len, 105 | void (*msg_cb)(char *msg, size_t len)); 106 | 107 | 108 | /** 109 | * wpa_ctrl_attach - Register as an event monitor for the control interface 110 | * @ctrl: Control interface data from wpa_ctrl_open() 111 | * Returns: 0 on success, -1 on failure, -2 on timeout 112 | * 113 | * This function registers the control interface connection as a monitor for 114 | * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the 115 | * control interface connection starts receiving event messages that can be 116 | * read with wpa_ctrl_recv(). 117 | */ 118 | int wpa_ctrl_attach(struct wpa_ctrl *ctrl); 119 | 120 | 121 | /** 122 | * wpa_ctrl_detach - Unregister event monitor from the control interface 123 | * @ctrl: Control interface data from wpa_ctrl_open() 124 | * Returns: 0 on success, -1 on failure, -2 on timeout 125 | * 126 | * This function unregisters the control interface connection as a monitor for 127 | * wpa_supplicant/hostapd events, i.e., cancels the registration done with 128 | * wpa_ctrl_attach(). 129 | */ 130 | int wpa_ctrl_detach(struct wpa_ctrl *ctrl); 131 | 132 | 133 | /** 134 | * wpa_ctrl_recv - Receive a pending control interface message 135 | * @ctrl: Control interface data from wpa_ctrl_open() 136 | * @reply: Buffer for the message data 137 | * @reply_len: Length of the reply buffer 138 | * Returns: 0 on success, -1 on failure 139 | * 140 | * This function will receive a pending control interface message. This 141 | * function will block if no messages are available. The received response will 142 | * be written to reply and reply_len is set to the actual length of the reply. 143 | * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach() 144 | * must have been used to register the control interface as an event monitor. 145 | */ 146 | int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); 147 | 148 | 149 | /** 150 | * wpa_ctrl_pending - Check whether there are pending event messages 151 | * @ctrl: Control interface data from wpa_ctrl_open() 152 | * Returns: 1 if there are pending messages, 0 if no, or -1 on error 153 | * 154 | * This function will check whether there are any pending control interface 155 | * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is 156 | * only used for event messages, i.e., wpa_ctrl_attach() must have been used to 157 | * register the control interface as an event monitor. 158 | */ 159 | int wpa_ctrl_pending(struct wpa_ctrl *ctrl); 160 | 161 | 162 | /** 163 | * wpa_ctrl_get_fd - Get file descriptor used by the control interface 164 | * @ctrl: Control interface data from wpa_ctrl_open() 165 | * Returns: File descriptor used for the connection 166 | * 167 | * This function can be used to get the file descriptor that is used for the 168 | * control interface connection. The returned value can be used, e.g., with 169 | * select() while waiting for multiple events. 170 | * 171 | * The returned file descriptor must not be used directly for sending or 172 | * receiving packets; instead, the library functions wpa_ctrl_request() and 173 | * wpa_ctrl_recv() must be used for this. 174 | */ 175 | int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); 176 | 177 | #ifdef CONFIG_CTRL_IFACE_UDP 178 | #define WPA_CTRL_IFACE_PORT 9877 179 | #define WPA_GLOBAL_CTRL_IFACE_PORT 9878 180 | #endif /* CONFIG_CTRL_IFACE_UDP */ 181 | 182 | 183 | #ifdef __cplusplus 184 | } 185 | #endif 186 | 187 | #endif /* WPA_CTRL_H */ 188 | -------------------------------------------------------------------------------- /src/id.c: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file id.c 4 | * @brief simple interface for managing node id 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #include 34 | #include 35 | #include "debug.h" 36 | #include "id.h" 37 | 38 | static nodeid_t nodeid = {0}; 39 | 40 | void co_id_set_from_mac(const unsigned char *mac, int mac_size) { 41 | nodeid.id = 0; 42 | CHECK(mac_size == 6, "MAC size is not six."); 43 | DEBUG("Received MAC Address : %02x:%02x:%02x:%02x:%02x:%02x\n", 44 | mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 45 | /* Load last four bytes of MAC address into nodeid struct*/ 46 | for(int i = 0; i < 4; i++) { 47 | nodeid.bytes[i] = mac[i + 2]; 48 | } 49 | error: 50 | return; 51 | } 52 | 53 | void co_id_set_from_int(const uint32_t n) { 54 | nodeid.id = htonl(n); 55 | return; 56 | } 57 | 58 | nodeid_t co_id_get(void) { 59 | return nodeid; 60 | } 61 | -------------------------------------------------------------------------------- /src/id.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file id.h 4 | * @brief simple interface for managing node id 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | #ifndef _ID_H 33 | #define _ID_H 34 | 35 | #include 36 | 37 | /** 38 | * @struct nodeid_t struct containing node id and last four bytes of MAC address 39 | */ 40 | typedef union { 41 | uint32_t id; 42 | uint8_t bytes[4]; 43 | } nodeid_t; 44 | 45 | /** 46 | * @brief sets node id using last four bytes of device's MAC address 47 | * @param mac the MAC address of the device 48 | * @param mac_size the size of the MAC address 49 | */ 50 | void co_id_set_from_mac(const unsigned char *mac, int mac_size); 51 | 52 | /** 53 | * @brief Converts node id from host byte order to network byte order 54 | * @param n the node id (4 bytes) 55 | */ 56 | void co_id_set_from_int(const uint32_t n); 57 | 58 | /** 59 | * @brief Returns nodeid 60 | */ 61 | nodeid_t co_id_get(void); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/iface.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file iface.h 4 | * @brief interface handling for the Commotion daemon 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #ifndef _IFACE_H 34 | #define _IFACE_H 35 | #include 36 | #include 37 | #include "id.h" 38 | #include "obj.h" 39 | 40 | #define FREQ_LEN 5 //number of characters in 802.11 frequency designator 41 | #define MAC_LEN 6 42 | #define WPA_REPLY_SIZE 2048 43 | #define IFACES_MAX 32 44 | #define SIOCGIWNAME 0x8B01 45 | 46 | /** 47 | * @enum co_iface_status_t indicates whether the interface is UP(1) or DOWN(0) 48 | */ 49 | typedef enum { 50 | DOWN = 0, 51 | UP = 1 52 | } co_iface_status_t; 53 | 54 | typedef struct co_iface_t co_iface_t; 55 | 56 | /** 57 | * @struct co_iface_t 58 | * @brief contains the file descriptor, interface status (up or down), profile name, interface frequency struct, wpa control struct, wpa id, and a bool to indicare whether the interface is wireless or not 59 | */ 60 | struct co_iface_t { 61 | co_obj_t _header; 62 | uint8_t _exttype; 63 | uint8_t _len; 64 | int fd; 65 | co_iface_status_t status; 66 | char *profile; 67 | struct ifreq ifr; 68 | struct wpa_ctrl *ctrl; 69 | int wpa_id; 70 | bool wireless; 71 | } __attribute__((packed)); 72 | 73 | /** 74 | * @brief checks for available interfaces 75 | */ 76 | int co_ifaces_create(void); 77 | 78 | /** 79 | * @brief removes all interfaces 80 | */ 81 | void co_ifaces_shutdown(void); 82 | 83 | /** 84 | * @brief removes an interface from the list of available interfaces 85 | * @param iface_name name of interface to be removed 86 | */ 87 | int co_iface_remove(char *iface_name); 88 | 89 | /** 90 | * @brief adds a new interface to the list of available interfaces, and checks whether it is IPv4 and IPv6 capable, and whether it is wireless 91 | * @param iface_name name of the interface 92 | * @param family address family of the interface. Must be AF_INET (IPv4) or AF_INET6 (IPv6), which uses host and port number for addressing 93 | */ 94 | co_obj_t *co_iface_add(const char *iface_name, const int family); 95 | 96 | /** 97 | * @brief connects the commotion interface to wpa supplicant 98 | * @param iface interface object 99 | */ 100 | int co_iface_wpa_connect(co_obj_t *iface); 101 | 102 | /** 103 | * @brief turns off wpa supplicant 104 | * @param iface interface object 105 | */ 106 | int co_iface_wpa_disconnect(co_obj_t *iface); 107 | 108 | /** 109 | * @brief 110 | * @param iface interface object 111 | * @param output output of hardware MAC address lookup 112 | * @param output_size size of MAC address. Must be six bytes 113 | */ 114 | int co_iface_get_mac(co_obj_t *iface, unsigned char *output, int output_size); 115 | 116 | /** 117 | * @brief sets ip address and netmask for commotion interface 118 | * @param iface interface object 119 | * @param ip_addr ip address for the socket 120 | * @param netmask netmask for the socket 121 | */ 122 | int co_iface_set_ip(co_obj_t *iface, const char *ip_addr, const char *netmask); 123 | 124 | /** 125 | * @brief Resets ip address of chosen interface 126 | * @param iface interface object 127 | */ 128 | int co_iface_unset_ip(co_obj_t *iface); 129 | 130 | /** 131 | * @brief sets SSID from profile or uses default 132 | * @param iface interface object 133 | * @param ssid desired SSID 134 | */ 135 | int co_iface_set_ssid(co_obj_t *iface, const char *ssid); 136 | 137 | /** 138 | * @brief sets BSSID from profile or uses default 139 | * @param iface interface object 140 | * @param bssid desired BSSID 141 | */ 142 | int co_iface_set_bssid(co_obj_t *iface, const char *bssid); 143 | 144 | /** 145 | * @brief sets wireless frequency (eg. channel) from profile or uses default 146 | * @param iface interface object 147 | * @param frequency desired frequency 148 | */ 149 | int co_iface_set_frequency(co_obj_t *iface, const int frequency); 150 | 151 | /** 152 | * @brief specifies the wpa encryption protocol 153 | * @param iface interface object 154 | * @param proto desired protocol 155 | */ 156 | int co_iface_set_encryption(co_obj_t *iface, const char *proto); 157 | 158 | /** 159 | * @brief specifies the wpa encryption key 160 | * @param iface interface object 161 | * @param key desired key 162 | */ 163 | int co_iface_set_key(co_obj_t *iface, const char *key); 164 | 165 | /** 166 | * @brief specifies the Wi-Fi mode 167 | * @param iface interface object 168 | * @param mode desired mode 169 | */ 170 | int co_iface_set_mode(co_obj_t *iface, const char *mode); 171 | 172 | /** 173 | * @brief sets AP_SCAN value 174 | * @param iface interface object 175 | * @param value desired value for AP_SCAN 176 | */ 177 | int co_iface_set_apscan(co_obj_t *iface, const int value); 178 | 179 | /** 180 | * @brief enables specified wireless network 181 | * @param iface interface object 182 | */ 183 | int co_iface_wireless_enable(co_obj_t *iface); 184 | 185 | /** 186 | * @brief disables specified wireless network 187 | * @param iface interface object 188 | */ 189 | int co_iface_wireless_disable(co_obj_t *iface); 190 | 191 | /** 192 | * @brief sets DNS name server and sets search domain 193 | * @param dnsserver IP addresss of DNS server 194 | * @param searchdomain desired search domain 195 | * @param resolvpath filepath to resolv.conf 196 | */ 197 | int co_set_dns(const char *dnsserver, const char *searchdomain, const char *resolvpath); 198 | 199 | //int co_set_dns(const char *dnsservers[], const size_t numservers, const char *searchdomain, const char *resolvpath); 200 | 201 | /** 202 | * @brief generates an ip table for a commotion interface 203 | * @param base base address 204 | * @param genmask genmask 205 | * @param id the node id 206 | * @param type whether the device is a gateway (1) or not (0) 207 | */ 208 | int co_generate_ip(const char *base, const char *genmask, const nodeid_t id, char *output, int type); 209 | 210 | //int co_iface_status(const char *iface_name); 211 | 212 | /** 213 | * @brief sets node configuration profile 214 | * @param iface_name name of interface 215 | */ 216 | char *co_iface_profile(char *iface_name); 217 | 218 | /** 219 | * @brief retrieves node configuration profile 220 | * @param iface_name name of interface 221 | */ 222 | co_obj_t *co_iface_get(char *iface_name); 223 | 224 | #endif 225 | -------------------------------------------------------------------------------- /src/list.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file list.h 4 | * @brief Commotion double linked-list implementation 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 11/14/2013 11:22:20 AM 10 | * Compiler gcc/g++ 11 | * Organization The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Josh King 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU Affero General Public License as 18 | * published by the Free Software Foundation, either version 3 of the 19 | * License, or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU Affero General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU Affero General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | #ifndef _LIST_H 32 | #define _LIST_H 33 | #include 34 | #include 35 | #include 36 | #include "debug.h" 37 | #include "extern/halloc.h" 38 | 39 | typedef struct _listnode_t _listnode_t; 40 | 41 | /* Type "list" declaration macros */ 42 | #define _DECLARE_LIST(L) typedef struct __attribute__((packed)) \ 43 | { co_obj_t _header; uint##L##_t _len; _listnode_t *_first; _listnode_t *_last; } co_list##L##_t; \ 44 | int co_list##L##_alloc(co_obj_t *output); co_obj_t *\ 45 | co_list##L##_create(void); 46 | 47 | _DECLARE_LIST(16); 48 | _DECLARE_LIST(32); 49 | 50 | /** 51 | * @brief return length (number of objects) of given list 52 | * @param list list object 53 | */ 54 | ssize_t co_list_length(co_obj_t *list); 55 | 56 | /** 57 | * @brief return first element of given list 58 | * @param list list object 59 | */ 60 | co_obj_t * co_list_get_first(const co_obj_t *list); 61 | 62 | /** 63 | * @brief return last element of given list 64 | * @param list list object 65 | */ 66 | co_obj_t * co_list_get_last(const co_obj_t *list); 67 | 68 | /** 69 | * @brief process list with given iterator function 70 | * @param list list object to process 71 | * @param iter iterator function 72 | * @param context additional arguments to iterator 73 | */ 74 | co_obj_t * co_list_parse(co_obj_t *list, co_iter_t iter, void *context); 75 | 76 | /** 77 | * @brief determine if list contains specified item 78 | * @param list list object to process 79 | * @param item item to search for 80 | */ 81 | int co_list_contains(co_obj_t *list, co_obj_t *item); 82 | 83 | /** 84 | * @brief insert new item in list before specified item 85 | * @param list list object to process 86 | * @param new_obj item to insert 87 | * @param this_obj item to insert before 88 | */ 89 | int co_list_insert_before(co_obj_t *list, co_obj_t *new_obj, \ 90 | co_obj_t *this_obj); 91 | 92 | /** 93 | * @brief insert new item in list before specified item without the list managing the item's memory 94 | * @param list list object to process 95 | * @param new_obj item to insert 96 | * @param this_obj item to insert before 97 | */ 98 | int co_list_insert_before_unsafe(co_obj_t *list, co_obj_t *new_obj, \ 99 | co_obj_t *this_obj); 100 | 101 | /** 102 | * @brief insert new item in list after specified item 103 | * @param list list object to process 104 | * @param new_obj item to insert 105 | * @param this_obj item to insert after 106 | */ 107 | int co_list_insert_after(co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj); 108 | 109 | /** 110 | * @brief insert new item in list after specified item without the list managing the item's memory 111 | * @param list list object to process 112 | * @param new_obj item to insert 113 | * @param this_obj item to insert after 114 | */ 115 | int co_list_insert_after_unsafe(co_obj_t *list, co_obj_t *new_obj, co_obj_t *this_obj); 116 | 117 | /** 118 | * @brief insert new item at beginning of list 119 | * @param list list object to process 120 | * @param new_obj item to insert 121 | */ 122 | int co_list_prepend(co_obj_t *list, co_obj_t *new_obj); 123 | 124 | /** 125 | * @brief insert new item at beginning of list without the list managing the item's memory 126 | * @param list list object to process 127 | * @param new_obj item to insert 128 | */ 129 | int co_list_prepend_unsafe(co_obj_t *list, co_obj_t *new_obj); 130 | 131 | /** 132 | * @brief insert new item at end of list 133 | * @param list list object to process 134 | * @param new_obj item to insert 135 | */ 136 | int co_list_append(co_obj_t *list, co_obj_t *new_obj); 137 | 138 | /** 139 | * @brief insert new item at end of list without the list managing the item's memory 140 | * @param list list object to process 141 | * @param new_obj item to insert 142 | */ 143 | int co_list_append_unsafe(co_obj_t *list, co_obj_t *new_obj); 144 | 145 | /** 146 | * @brief delete specified item from list 147 | * @param list list object to process 148 | * @param item item to delete 149 | */ 150 | co_obj_t *co_list_delete(co_obj_t *list, co_obj_t *item); 151 | 152 | /** 153 | * @brief return item at specified position in list 154 | * @param list list object to process 155 | * @param index number of item to return 156 | */ 157 | co_obj_t *co_list_element(co_obj_t *list, const unsigned int index); 158 | 159 | /** 160 | * @brief dump raw representation of list 161 | * @param output output buffer 162 | * @param olen length of output buffer 163 | * @param list list object to process 164 | */ 165 | ssize_t co_list_raw(char *output, const size_t olen, const co_obj_t *list); 166 | 167 | /** 168 | * @brief import list from raw representation 169 | * @param list target pointer to new list object 170 | * @param input input buffer 171 | * @param ilen length of input buffer 172 | */ 173 | ssize_t co_list_import(co_obj_t **list, const char *input, const size_t ilen); 174 | 175 | /** 176 | * @brief print list with indent 177 | * @param list list object to print 178 | * @param indent level of indent 179 | */ 180 | void co_list_print_indent(co_obj_t *list, int indent); 181 | 182 | /** 183 | * @brief print list 184 | * @param list list object to print 185 | */ 186 | int co_list_print(co_obj_t *list); 187 | 188 | #endif 189 | -------------------------------------------------------------------------------- /src/loop.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file loop.h 4 | * @brief a simple object-oriented event loop 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #ifndef _LOOP_H 34 | #define _LOOP_H 35 | 36 | #include 37 | #include "process.h" 38 | #include "socket.h" 39 | 40 | #define LOOP_MAXPROC 20 41 | #define LOOP_MAXSOCK 20 42 | #define LOOP_MAXEVENT 64 43 | #define LOOP_TIMEOUT 5 44 | #define LOOP_MAXTIMER 20 45 | 46 | typedef struct co_timer_t co_timer_t; 47 | 48 | struct co_timer_t { 49 | co_obj_t _header; 50 | uint8_t _exttype; 51 | uint8_t _len; 52 | bool pending; 53 | struct timeval deadline; 54 | co_cb_t timer_cb; 55 | void *ptr; 56 | } __attribute__((packed)); 57 | 58 | //Public functions 59 | 60 | /** 61 | * @brief sets up the event loop 62 | */ 63 | int co_loop_create(void); 64 | 65 | /** 66 | * @brief closes the event loop 67 | */ 68 | int co_loop_destroy(void); 69 | 70 | /** 71 | * @brief starts the event loop, listening for messages on sockets via _co_loop_poll_sockets 72 | */ 73 | void co_loop_start(void); 74 | 75 | /** 76 | * @brief stops the event loop 77 | */ 78 | void co_loop_stop(void); 79 | 80 | /** 81 | * @brief adds a process to the event loop (for it to listen for) 82 | * @param proc the process to be added 83 | */ 84 | int co_loop_add_process(co_obj_t *proc); 85 | 86 | /** 87 | * @brief removes a process from the event loop 88 | * @param pid the id of the process to be removed 89 | */ 90 | int co_loop_remove_process(pid_t pid); 91 | 92 | /** 93 | * @brief adds a new socket to the event loop (for it to listen on) 94 | * @param new_sock the new socket to be added 95 | * @param context a co_obj_t context pointer (currently unused) 96 | */ 97 | int co_loop_add_socket(co_obj_t *new_sock, co_obj_t *context); 98 | 99 | /** 100 | * @brief removes a socket from the event loop 101 | * @param old_sock the socket to be removed 102 | * @param context a co_obj_t context pointer (currently unused) 103 | */ 104 | int co_loop_remove_socket(co_obj_t *old_sock, co_obj_t *context); 105 | 106 | /** 107 | * @brief gets a socket that is registered with the event loop 108 | * @param uri a URI to match against the available sockets 109 | * @param context a co_obj_t context pointer (currently unused) 110 | */ 111 | co_obj_t *co_loop_get_socket(char *uri, co_obj_t *context); 112 | 113 | /** 114 | * @brief schedules a new timer with the event loop 115 | * @param timer the timer to schedule 116 | * @param context a co_obj_t context pointer (currently unused) 117 | */ 118 | int co_loop_add_timer(co_obj_t *new_timer, co_obj_t *context); 119 | 120 | /** 121 | * @brief removes a timer from the event loop 122 | * @param old_timer the timer to remove from list 123 | * @param context a co_obj_t context pointer (currently unused) 124 | */ 125 | int co_loop_remove_timer(co_obj_t *old_timer, co_obj_t *context); 126 | 127 | /** 128 | * @brief sets timer to expire in msecs from now 129 | * @param timer the timer to set 130 | * @param msecs number of milliseconds 131 | * @param context a co_obj_t context pointer (currently unused) 132 | */ 133 | int co_loop_set_timer(co_obj_t *timer, long msecs, co_obj_t *context); 134 | 135 | /** 136 | * @brief gets a socket that is registered with the event loop 137 | * @param ptr void pointer to match against the available timers 138 | * @param context a co_obj_t context pointer (currently unused) 139 | */ 140 | co_obj_t *co_loop_get_timer(void *ptr, co_obj_t *context); 141 | 142 | /** 143 | * @brief malloc and initialize a timer 144 | * @param size timer struct size 145 | * @param proto timer protocol 146 | */ 147 | co_obj_t *co_timer_create(struct timeval deadline, co_cb_t timer_cb, void *ptr); 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /src/msg.c: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file msg.c 4 | * @brief a simple message serialization library 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "debug.h" 40 | #include "util.h" 41 | #include "msg.h" 42 | #include "obj.h" 43 | #include "list.h" 44 | #include "tree.h" 45 | 46 | static uint32_t _id = 0; 47 | 48 | static struct 49 | { 50 | uint8_t list_type; 51 | uint16_t list_len; 52 | uint8_t type_type; 53 | uint8_t type_value; 54 | uint8_t id_type; 55 | } _req_header = { 56 | .list_type = _list16, 57 | .list_len = 4, 58 | .type_type = _uint8, 59 | .type_value = 0, 60 | .id_type = _uint32 61 | }; 62 | 63 | size_t 64 | co_request_alloc(char *output, const size_t olen, const co_obj_t *method, co_obj_t *param) 65 | { 66 | 67 | CHECK(((output != NULL) && (method != NULL)), "Invalid request components."); 68 | CHECK(olen > sizeof(_req_header) + sizeof(uint32_t) + sizeof(co_str16_t) + sizeof(co_list16_t), "Output buffer too small."); 69 | ssize_t written = 0, s = 0; 70 | char *cursor = NULL; 71 | 72 | /* Pack request header */ 73 | memmove(output + written, &_req_header.list_type, sizeof(_req_header.list_type)); 74 | written += sizeof(_req_header.list_type); 75 | 76 | memmove(output + written, &_req_header.list_len, sizeof(_req_header.list_len)); 77 | written += sizeof(_req_header.list_len); 78 | 79 | memmove(output + written, &_req_header.type_type, sizeof(_req_header.type_type)); 80 | written += sizeof(_req_header.type_type); 81 | 82 | memmove(output + written, &_req_header.type_value, sizeof(_req_header.type_value)); 83 | written += sizeof(_req_header.type_value); 84 | 85 | memmove(output + written, &_req_header.id_type, sizeof(_req_header.id_type)); 86 | written += sizeof(_req_header.id_type); 87 | 88 | /* Pack request ID */ 89 | memmove(output + written, &_id, sizeof(uint32_t)); 90 | written += sizeof(uint32_t); 91 | _id++; 92 | 93 | /* Pack method call */ 94 | CHECK(IS_STR(method), "Not a valid method name."); 95 | char *buffer = NULL; 96 | ssize_t buffer_write = co_obj_raw(&buffer, method); 97 | CHECK(buffer_write >= 0, "Failed to pack object."); 98 | memmove(output + written, buffer, buffer_write); 99 | written += buffer_write; 100 | 101 | /* Pack parameters */ 102 | CHECK(written < olen, "Output buffer too small."); 103 | if(param != NULL) 104 | { 105 | if(IS_LIST(param)) 106 | { 107 | s = co_list_raw(output + written, olen - written, param); 108 | CHECK(s > 0, "Failed to pack list parameter"); 109 | written += s; 110 | } 111 | else 112 | { 113 | s = co_obj_raw(&cursor, param); 114 | CHECK(s > 0, "Failed to pack object parameter"); 115 | written += s; 116 | memmove(output + written, cursor, s); 117 | } 118 | } 119 | CHECK(written >= 0, "Failed to pack object."); 120 | DEBUG("Request bytes written: %d", (int)written); 121 | CHECK(written < olen, "Output buffer too small."); 122 | 123 | return written; 124 | error: 125 | return -1; 126 | 127 | } 128 | 129 | static struct 130 | { 131 | uint8_t list_type; 132 | uint16_t list_len; 133 | uint8_t type_type; 134 | uint8_t type_value; 135 | uint8_t id_type; 136 | } _resp_header = { 137 | .list_type = _list16, 138 | .list_len = 4, 139 | .type_type = _uint8, 140 | .type_value = 1, 141 | .id_type = _uint32 142 | }; 143 | 144 | size_t 145 | co_response_alloc(char *output, const size_t olen, const uint32_t id, const co_obj_t *error, co_obj_t *result) 146 | { 147 | CHECK(((output != NULL) && (error != NULL) && (result != NULL)), "Invalid response components."); 148 | CHECK(olen > sizeof(_resp_header) + sizeof(uint32_t) + sizeof(co_str16_t) + sizeof(co_list16_t), "Output buffer too small."); 149 | ssize_t written = 0, s = 0; 150 | char *cursor = NULL; 151 | 152 | /* Pack response header */ 153 | memmove(output + written, &_resp_header.list_type, sizeof(_resp_header.list_type)); 154 | written += sizeof(_resp_header.list_type); 155 | 156 | memmove(output + written, &_resp_header.list_len, sizeof(_resp_header.list_len)); 157 | written += sizeof(_resp_header.list_len); 158 | 159 | memmove(output + written, &_resp_header.type_type, sizeof(_resp_header.type_type)); 160 | written += sizeof(_resp_header.type_type); 161 | 162 | memmove(output + written, &_resp_header.type_value, sizeof(_resp_header.type_value)); 163 | written += sizeof(_resp_header.type_value); 164 | 165 | memmove(output + written, &_resp_header.id_type, sizeof(_resp_header.id_type)); 166 | written += sizeof(_resp_header.id_type); 167 | 168 | /* Pack response ID */ 169 | memmove(output + written, &id, sizeof(uint32_t)); 170 | written += sizeof(uint32_t); 171 | 172 | /* Pack error code */ 173 | //CHECK(IS_STR(error) || IS_NIL(error), "Not a valid error name."); 174 | if(error != NULL) 175 | { 176 | if(IS_LIST(error)) 177 | { 178 | s = co_list_raw(output + written, olen - written, error); 179 | CHECK(s > 0, "Failed to pack list parameter"); 180 | written += s; 181 | } 182 | else if(IS_TREE(error)) 183 | { 184 | s = co_tree_raw(output + written, olen - written, error); 185 | CHECK(s > 0, "Failed to pack tree parameter"); 186 | written += s; 187 | } 188 | else 189 | { 190 | s = co_obj_raw(&cursor, error); 191 | CHECK(s > 0, "Failed to pack object parameter"); 192 | memmove(output + written, cursor, s); 193 | written += s; 194 | } 195 | } 196 | 197 | /* Pack method result */ 198 | CHECK(written < olen, "Output buffer too small."); 199 | if(result != NULL) 200 | { 201 | if(IS_LIST(result)) 202 | { 203 | s = co_list_raw(output + written, olen - written, result); 204 | CHECK(s > 0, "Failed to pack list parameter"); 205 | written += s; 206 | } 207 | else if(IS_TREE(result)) 208 | { 209 | s = co_tree_raw(output + written, olen - written, result); 210 | CHECK(s > 0, "Failed to pack tree parameter"); 211 | written += s; 212 | } 213 | else 214 | { 215 | s = co_obj_raw(&cursor, result); 216 | CHECK(s > 0, "Failed to pack object parameter"); 217 | memmove(output + written, cursor, s); 218 | written += s; 219 | } 220 | } 221 | 222 | DEBUG("Response bytes written: %d", (int)written); 223 | CHECK(written < olen, "Output buffer too small."); 224 | 225 | return written; 226 | error: 227 | return -1; 228 | } 229 | -------------------------------------------------------------------------------- /src/msg.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file msg.h 4 | * @brief a simple message serialization library 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #ifndef _MSG_H 34 | #define _MSG_H 35 | 36 | #include 37 | #include 38 | #include 39 | #include "obj.h" 40 | 41 | /** 42 | * @brief allocate request 43 | * @param output buffer for output 44 | * @param olen output buffer length 45 | * @param method name of method 46 | * @param param parameters to method 47 | */ 48 | size_t co_request_alloc(char *output, const size_t olen, const co_obj_t *method, co_obj_t *param); 49 | 50 | /** 51 | * @brief allocate response 52 | * @param output buffer for output 53 | * @param olen output buffer length 54 | * @param id response ID 55 | * @param error error object 56 | * @param result result of request 57 | */ 58 | size_t co_response_alloc(char *output, const size_t olen, const uint32_t id, const co_obj_t *error, co_obj_t *result); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/plugin.c: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file plugin.c 4 | * @brief The commotiond plugin loader. 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 11/04/2013 10:47:37 AM 10 | * Compiler gcc/g++ 11 | * Organization The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Josh King 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU Affero General Public License as 18 | * published by the Free Software Foundation, either version 3 of the 19 | * License, or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU Affero General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU Affero General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "obj.h" 37 | #include "cmd.h" 38 | #include "list.h" 39 | #include "debug.h" 40 | #include "util.h" 41 | #include "plugin.h" 42 | 43 | static co_obj_t* _plugins = NULL; 44 | 45 | 46 | static co_obj_t * 47 | _co_plugins_shutdown_i(co_obj_t *data, co_obj_t *current, void *context) 48 | { 49 | if(((co_plugin_t *)current)->shutdown != NULL) 50 | { 51 | ((co_plugin_t *)current)->shutdown(current, NULL, NULL); 52 | } 53 | if(((co_plugin_t *)current)->handle != NULL) 54 | { 55 | dlclose(((co_plugin_t *)current)->handle); 56 | } 57 | co_list_delete(_plugins,current); 58 | co_obj_free(current); 59 | return NULL; 60 | } 61 | 62 | int 63 | co_plugins_shutdown(void) 64 | { 65 | co_list_parse(_plugins, _co_plugins_shutdown_i, NULL); 66 | CHECK(co_list_length(_plugins) == 0, "Failed to shutdown all plugins."); 67 | co_obj_free(_plugins); 68 | return 1; 69 | error: 70 | co_obj_free(_plugins); 71 | return 0; 72 | } 73 | 74 | static co_obj_t * 75 | _co_plugins_start_i(co_obj_t *data, co_obj_t *current, void *context) 76 | { 77 | if (IS_PLUG(current)) 78 | CHECK(((co_plugin_t *)current)->init(current, NULL, NULL),"Failed to start plugin %s",co_obj_data_ptr(((co_plugin_t *)current)->name)); 79 | return NULL; 80 | error: 81 | return current; 82 | } 83 | 84 | int 85 | co_plugins_start(void) 86 | { 87 | CHECK(co_list_parse(_plugins, _co_plugins_start_i, NULL) == NULL,"Failed to start all plugins"); 88 | return 1; 89 | error: 90 | return 0; 91 | } 92 | 93 | int 94 | co_plugins_init(size_t index_size) 95 | { 96 | if(index_size == 16) 97 | { 98 | CHECK((_plugins = (co_obj_t *)co_list16_create()) != NULL, "Plugin list creation failed."); 99 | } 100 | else if(index_size == 32) 101 | { 102 | CHECK((_plugins = (co_obj_t *)co_list32_create()) != NULL, "Plugin list creation failed."); 103 | } 104 | else SENTINEL("Invalid list index size."); 105 | 106 | return 1; 107 | 108 | error: 109 | co_plugins_shutdown(); 110 | return 0; 111 | } 112 | 113 | static int _co_plugins_load_i(const char *path, const char *filename) { 114 | char path_tmp[PATH_MAX] = {}; 115 | strlcpy(path_tmp, path, PATH_MAX); 116 | strlcat(path_tmp, "/", PATH_MAX); 117 | strlcat(path_tmp, filename, PATH_MAX); 118 | dlerror(); //Clear existing error codes. 119 | void *handle = dlopen(path_tmp, RTLD_GLOBAL|RTLD_NOW); 120 | CHECK(handle != NULL, "Failed to load plugin %s: %s", path_tmp, dlerror()); 121 | co_cb_t co_plugin_name = dlsym(handle, "co_plugin_name"); 122 | CHECK(co_plugin_name != NULL, "Failed to name plugin %s: %s", path_tmp, dlerror()); 123 | co_cb_t co_plugin_register = dlsym(handle, "co_plugin_register"); 124 | co_cb_t co_plugin_init = dlsym(handle, "co_plugin_init"); 125 | CHECK(co_plugin_init != NULL, "Failed to init plugin %s: %s", path_tmp, dlerror()); 126 | co_cb_t co_plugin_shutdown = dlsym(handle, "co_plugin_shutdown"); 127 | 128 | //TODO: API version checks. 129 | co_plugin_t *plugin = h_calloc(1, sizeof(co_plugin_t)); 130 | plugin->handle = handle; 131 | 132 | CHECK(co_plugin_name(NULL, &(plugin->name), NULL), "Failed to set plugin name."); 133 | hattach(plugin->name, plugin); 134 | CHECK_MEM(plugin->filename = co_str8_create(filename, strlen(filename)+1, 0)); 135 | hattach(plugin->filename, plugin); 136 | if(co_plugin_shutdown != NULL) plugin->shutdown = co_plugin_shutdown; 137 | plugin->init = co_plugin_init; 138 | plugin->_len = (sizeof(co_plugin_t)); 139 | plugin->_exttype = _plug; 140 | plugin->_header._type = _ext8; 141 | plugin->_header._ref = 0; 142 | plugin->_header._flags = 0; 143 | if(co_plugin_register != NULL) co_plugin_register((co_obj_t *)plugin, NULL, NULL); 144 | 145 | co_list_append(_plugins, (co_obj_t *)plugin); 146 | return 1; 147 | error: 148 | if(handle != NULL) dlclose(handle); 149 | if(plugin != NULL) co_obj_free((co_obj_t *)plugin); 150 | return 1; 151 | } 152 | 153 | int co_plugins_load(const char *dir_path) { 154 | return process_files(dir_path, _co_plugins_load_i); 155 | } 156 | -------------------------------------------------------------------------------- /src/plugin.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file plugin.h 4 | * @brief The commotiond plugin loader. 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 11/04/2013 10:47:37 AM 10 | * Compiler gcc/g++ 11 | * Organization The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Josh King 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU Affero General Public License as 18 | * published by the Free Software Foundation, either version 3 of the 19 | * License, or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU Affero General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU Affero General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | 32 | #ifndef _PLUGIN_H 33 | #define _PLUGIN_H 34 | 35 | #include 36 | #include "obj.h" 37 | 38 | typedef struct co_plugin_t co_plugin_t; 39 | 40 | /** 41 | * @struct co_plugin_t contains file path, descriptor and name information for plugins 42 | */ 43 | struct co_plugin_t { 44 | co_obj_t _header; 45 | uint8_t _exttype; 46 | uint8_t _len; 47 | co_obj_t *name; /**< command name */ 48 | co_obj_t *filename; 49 | co_cb_t shutdown; 50 | co_cb_t init; 51 | void *handle; 52 | } __attribute__((packed)); 53 | 54 | /** 55 | * @brief shuts down and closes all plugins 56 | */ 57 | int co_plugins_shutdown(void); 58 | 59 | /** 60 | * @brief starts all loaded plugins 61 | */ 62 | int co_plugins_start(void); 63 | 64 | /** 65 | * @brief initializes global plugin list 66 | * @param index_size specifies size of index for plugins list (16 or 32 bit) 67 | */ 68 | int co_plugins_init(size_t index_size); 69 | 70 | /** 71 | * @brief loads all plugins in specified path 72 | * @param dir_path directory to load plugins from 73 | */ 74 | int co_plugins_load(const char *dir_path); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/process.c: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file process.c 4 | * @brief a simple object-oriented process manager 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * object model inspired by Zed Shaw 8 | * 9 | * @internal 10 | * Created 03/07/2013 11 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 12 | * Compiler gcc/g++ 13 | * Company The Open Technology Institute 14 | * Copyright Copyright (c) 2013, Josh King 15 | * 16 | * This file is part of Commotion, Copyright (c) 2013, Josh King 17 | * 18 | * Commotion is free software: you can redistribute it and/or modify 19 | * it under the terms of the GNU Affero General Public License as 20 | * published by the Free Software Foundation, either version 3 of the 21 | * License, or (at your option) any later version. 22 | * 23 | * Commotion is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | * GNU Affero General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU Affero General Public License 29 | * along with Commotion. If not, see . 30 | * 31 | * ===================================================================================== 32 | */ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "debug.h" 41 | #include "process.h" 42 | #include "util.h" 43 | 44 | co_obj_t *co_process_create(const size_t size, co_process_t proto, const char *name, const char *pid_file, const char *exec_path, const char *run_path) { 45 | if(!proto.init) proto.init = NULL; 46 | if(!proto.destroy) proto.destroy = co_process_destroy; 47 | if(!proto.start) proto.start = co_process_start; 48 | if(!proto.stop) proto.stop = co_process_stop; 49 | 50 | co_process_t *new_proc = h_calloc(1,size); 51 | *new_proc = proto; 52 | new_proc->_header._type = _ext8; 53 | new_proc->_exttype = _process; 54 | new_proc->_len = size; 55 | 56 | CHECK_MEM(new_proc); 57 | 58 | new_proc->name = h_strdup(name); 59 | hattach(new_proc->name,new_proc); 60 | new_proc->pid_file = h_strdup(pid_file); 61 | hattach(new_proc->pid_file,new_proc); 62 | new_proc->exec_path = h_strdup(exec_path); 63 | hattach(new_proc->exec_path,new_proc); 64 | new_proc->run_path = h_strdup(run_path); 65 | hattach(new_proc->run_path,new_proc); 66 | 67 | if(!new_proc->init((co_obj_t*)new_proc)) { 68 | SENTINEL("Failed to initialize new process."); 69 | } else { 70 | return (co_obj_t*)new_proc; 71 | } 72 | 73 | error: 74 | new_proc->destroy((co_obj_t*)new_proc); 75 | return NULL; 76 | } 77 | 78 | int co_process_destroy(co_obj_t *self) { 79 | CHECK_MEM(self); 80 | CHECK(IS_PROCESS(self),"Not a process."); 81 | 82 | co_obj_free(self); 83 | 84 | return 1; 85 | 86 | error: 87 | return 0; 88 | } 89 | 90 | // TODO use co_list16_t instead of *argv[] 91 | int co_process_start(co_obj_t *self, char *argv[]) { 92 | CHECK_MEM(self); 93 | CHECK(IS_PROCESS(self),"Not a process."); 94 | co_process_t *this = (co_process_t*)self; 95 | char *exec = NULL; 96 | CHECK(((exec = this->exec_path) != NULL), "Invalid exec path!"); 97 | int pid = 0; 98 | int local_stdin_pipe[2], local_stdout_pipe[2]; 99 | 100 | if(pipe(local_stdin_pipe)) { 101 | ERROR("Could not initialize stdin pipe."); 102 | return 0; 103 | } 104 | if(pipe(local_stdout_pipe)) { 105 | ERROR("Could not initialize stdout pipe."); 106 | return 0; 107 | } 108 | 109 | if (!(pid = fork())) { 110 | dup2(local_stdin_pipe[0], 0); 111 | dup2(local_stdout_pipe[1], 1); 112 | 113 | close(local_stdin_pipe[0]); 114 | close(local_stdin_pipe[1]); 115 | close(local_stdout_pipe[0]); 116 | close(local_stdout_pipe[1]); 117 | 118 | CHECK((execvp(exec, argv) != -1), "Failed to exec!"); 119 | } 120 | INFO("fork()ed: %d\n", pid); 121 | this->pid = pid; 122 | 123 | this->input = local_stdin_pipe[1]; 124 | this->output = local_stdout_pipe[0]; 125 | 126 | close(local_stdin_pipe[0]); 127 | close(local_stdout_pipe[1]); 128 | 129 | return 1; 130 | 131 | error: 132 | exit(1); 133 | return 0; 134 | } 135 | 136 | int co_process_stop(co_obj_t *self) { 137 | CHECK_MEM(self); 138 | CHECK(IS_PROCESS(self),"Not a process."); 139 | co_process_t *this = (co_process_t*)self; 140 | CHECK(!(kill(this->pid, SIGKILL)), "Failed to kill co_process_t %d.", this->pid); 141 | 142 | return 1; 143 | 144 | error: 145 | return 0; 146 | } 147 | 148 | int co_process_restart(co_obj_t *self) { 149 | CHECK_MEM(self); 150 | CHECK(IS_PROCESS(self),"Not a process."); 151 | co_process_t *this = (co_process_t*)self; 152 | if(this->stop((co_obj_t*)this)) this->start((co_obj_t*)this, NULL); 153 | 154 | return 1; 155 | 156 | error: 157 | return 0; 158 | } 159 | -------------------------------------------------------------------------------- /src/process.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file process.h 4 | * @brief a simple object-oriented process manager 5 | * object model inspired by Zed Shaw 6 | * 7 | * @author Josh King (jheretic), jking@chambana.net 8 | * 9 | * @internal 10 | * Created 03/07/2013 11 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 12 | * Compiler gcc/g++ 13 | * Company The Open Technology Institute 14 | * Copyright Copyright (c) 2013, Josh King 15 | * 16 | * This file is part of Commotion, Copyright (c) 2013, Josh King 17 | * 18 | * Commotion is free software: you can redistribute it and/or modify 19 | * it under the terms of the GNU Affero General Public License as 20 | * published by the Free Software Foundation, either version 3 of the 21 | * License, or (at your option) any later version. 22 | * 23 | * Commotion is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | * GNU Affero General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU Affero General Public License 29 | * along with Commotion. If not, see . 30 | * 31 | * ===================================================================================== 32 | */ 33 | 34 | #ifndef _PROCESS_H 35 | #define _PROCESS_H 36 | 37 | #include 38 | #include 39 | #include "util.h" 40 | #include "obj.h" 41 | 42 | /** 43 | * @enum co_process_state_t defines the state of the process 44 | */ 45 | typedef enum { 46 | _STOPPING = 0, 47 | _STOPPED =1, 48 | _STARTING = 2, 49 | _STARTED = 3, 50 | _FAILED = -1 51 | } co_process_state_t; 52 | 53 | typedef struct co_process_t co_process_t; 54 | 55 | /** 56 | * @struct co_process_t process struct, including process id, run path and state information 57 | */ 58 | struct co_process_t { 59 | co_obj_t _header; 60 | uint8_t _exttype; 61 | uint8_t _len; 62 | int pid; 63 | bool registered; 64 | bool use_watchdog; 65 | co_process_state_t state; 66 | char *name; 67 | char *pid_file; 68 | char *exec_path; 69 | char *run_path; 70 | int input; 71 | int output; 72 | int (*init)(co_obj_t *self); 73 | int (*destroy)(co_obj_t *self); 74 | int (*start)(co_obj_t *self, char *argv[]); 75 | int (*stop)(co_obj_t *self); 76 | int (*restart)(co_obj_t *self); 77 | } __attribute__((packed)); 78 | 79 | /** 80 | * @brief creates a new commotion process 81 | * @param size size of the process 82 | * @param co_process_t protocol 83 | * @param name name of the process 84 | * @param pid_file the lockfile where the process id is stored 85 | * @param exec_path the execution path 86 | * @param run_path the run path 87 | * @return co_process_t to be registered with the daemon 88 | */ 89 | co_obj_t *co_process_create(size_t size, co_process_t proto, const char *name, const char *pid_file, const char *exec_path, const char *run_path); 90 | 91 | /** 92 | * @brief removes a process from commotiond 93 | * @param self pointer to the process' struct 94 | */ 95 | int co_process_destroy(co_obj_t *self); 96 | 97 | /** 98 | * @brief starts a selected process 99 | * @param self pointer to the process' struct 100 | * @param argv[] execution path for the process 101 | */ 102 | int co_process_start(co_obj_t *self, char *argv[]); 103 | 104 | /** 105 | * @brief stops a running process 106 | * @param self pointer to the process' struct 107 | */ 108 | int co_process_stop(co_obj_t *self); 109 | 110 | /** 111 | * @brief restarts a process 112 | * @param self pointer to the process' struct 113 | */ 114 | int co_process_restart(co_obj_t *self); 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /src/socket.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file socket.h 4 | * @brief a simple object-oriented socket wrapper 5 | * object model inspired by Zed Shaw 6 | * 7 | * @author Josh King (jheretic), jking@chambana.net 8 | * 9 | * @internal 10 | * Created 03/07/2013 11 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 12 | * Compiler gcc/g++ 13 | * Company The Open Technology Institute 14 | * Copyright Copyright (c) 2013, Josh King 15 | * 16 | * This file is part of Commotion, Copyright (c) 2013, Josh King 17 | * 18 | * Commotion is free software: you can redistribute it and/or modify 19 | * it under the terms of the GNU Affero General Public License as 20 | * published by the Free Software Foundation, either version 3 of the 21 | * License, or (at your option) any later version. 22 | * 23 | * Commotion is distributed in the hope that it will be useful, 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | * GNU Affero General Public License for more details. 27 | * 28 | * You should have received a copy of the GNU Affero General Public License 29 | * along with Commotion. If not, see . 30 | * 31 | * ===================================================================================== 32 | */ 33 | 34 | #ifndef _SOCKET_H 35 | #define _SOCKET_H 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "obj.h" 42 | 43 | #define MAX_IPPROTO 255 44 | #define MAX_CONNECTIONS 32 45 | 46 | typedef struct co_fd_t co_fd_t; 47 | typedef struct co_socket_t co_socket_t; 48 | 49 | struct co_fd_t { 50 | co_obj_t _header; 51 | uint8_t _exttype; 52 | uint8_t _len; 53 | co_socket_t *socket; // parent socket 54 | int fd; 55 | }; 56 | 57 | /** 58 | * @brief creates a file descriptor object 59 | * @param fd file descriptor int 60 | */ 61 | co_obj_t *co_fd_create(co_obj_t *parent, int fd); 62 | 63 | /** 64 | * @struct co_socket_t contains file path and state information for socket 65 | */ 66 | struct co_socket_t { 67 | co_obj_t _header; 68 | uint8_t _exttype; 69 | uint8_t _len; 70 | char *uri; 71 | co_fd_t *fd; //socket file descriptor 72 | co_obj_t *rfd_lst; //list of accepted socket file descriptors 73 | bool fd_registered; 74 | struct sockaddr* local; 75 | struct sockaddr* remote; 76 | bool listen; 77 | int (*init)(co_obj_t *self); 78 | int (*destroy)(co_obj_t *self); 79 | int (*hangup)(co_obj_t *self, co_obj_t *context); 80 | int (*bind)(co_obj_t *self, const char *endpoint); 81 | int (*connect)(co_obj_t *self, const char *endpoint); 82 | int (*send)(co_obj_t *self, char *outgoing, size_t length); 83 | int (*receive)(co_obj_t *self, co_obj_t *fd, char *incoming, size_t length); 84 | int (*setopt)(co_obj_t *self, int level, int option, void *optval, socklen_t optvallen); 85 | int (*getopt)(co_obj_t *self, int level, int option, void *optval, socklen_t optvallen); 86 | int (*poll_cb)(co_obj_t *self, co_obj_t *context); 87 | int (*register_cb)(co_obj_t *self, co_obj_t *context); 88 | unsigned int events; 89 | } __attribute__((packed)); 90 | 91 | /** 92 | * @brief creates a socket from specified values or initializes defaults 93 | * @param size size of socket struct 94 | * @param proto socket protocol 95 | */ 96 | co_obj_t *co_socket_create(size_t size, co_socket_t proto); 97 | 98 | /** 99 | * @brief creates a socket from specified values or initializes defaults 100 | * @param size size of socket struct 101 | * @param proto socket protocol 102 | */ 103 | int co_socket_init(co_obj_t *self); 104 | 105 | /** 106 | * @brief closes a socket and removes it from memory 107 | * @param self socket name 108 | */ 109 | int co_socket_destroy(co_obj_t *self); 110 | 111 | /** 112 | * @brief closes a socket and changes its state information 113 | * @param self socket name 114 | * @param context co_obj_t context pointer (currently unused) 115 | */ 116 | int co_socket_hangup(co_obj_t *self, co_obj_t *context); 117 | 118 | /** 119 | * @brief sends a message on a specified socket 120 | * @param self commotion file descriptor 121 | * @param outgoing message to be sent 122 | * @param length length of message 123 | */ 124 | int co_socket_send(co_obj_t *self, char *outgoing, size_t length); 125 | 126 | /** 127 | * @brief receives a message on the listening socket 128 | * @param self socket name 129 | * @param incoming message received 130 | * @param length length of message 131 | */ 132 | int co_socket_receive(co_obj_t * self, co_obj_t *fd, char *incoming, size_t length); 133 | 134 | /** 135 | * @brief sets custom socket options, if specified by user 136 | * @param self socket name 137 | * @param level the networking level to be customized 138 | * @param option the option to be changed 139 | * @param optval the value for the new option 140 | * @param optvallen the length of the value for the new option 141 | */ 142 | int co_socket_setopt(co_obj_t * self, int level, int option, void *optval, socklen_t optvallen); 143 | 144 | /** 145 | * @brief gets custom socket options specified from the user 146 | * @param self socket name 147 | * @param level the networking level to be customized 148 | * @param option the option to be changed 149 | * @param optval the value for the new option 150 | * @param optvallen the length of the value for the new option 151 | */ 152 | int co_socket_getopt(co_obj_t * self, int level, int option, void *optval, socklen_t optvallen); 153 | 154 | typedef struct unix_socket_t unix_socket_t; 155 | 156 | /** 157 | * @struct unix_socket_t struct for unix sockets. Contains protocol and file path to socket library 158 | */ 159 | struct unix_socket_t { 160 | co_socket_t proto; 161 | char *path; 162 | } __attribute__((packed)); 163 | 164 | /** 165 | * @brief initializes a unix socket 166 | * @param self socket name 167 | */ 168 | int unix_socket_init(co_obj_t *self); 169 | 170 | /** 171 | * @brief binds a unix socket to a specified endpoint 172 | * @param self socket name 173 | * @param endpoint specified endpoint for socket (file path) 174 | */ 175 | int unix_socket_bind(co_obj_t *self, const char *endpoint); 176 | 177 | /** 178 | * @brief connects a socket to specified endpoint 179 | * @param self socket name 180 | * @param endpoint specified endpoint for socket (file path) 181 | */ 182 | int unix_socket_connect(co_obj_t *self, const char *endpoint); 183 | 184 | 185 | #endif 186 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file util.h 4 | * @brief utility functions for the Commotion daemon 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 03/07/2013 10 | * Revision $Id: doxygen.commotion.templates,v 0.1 2013/01/01 09:00:00 jheretic Exp $ 11 | * Compiler gcc/g++ 12 | * Company The Open Technology Institute 13 | * Copyright Copyright (c) 2013, Josh King 14 | * 15 | * This file is part of Commotion, Copyright (c) 2013, Josh King 16 | * 17 | * Commotion is free software: you can redistribute it and/or modify 18 | * it under the terms of the GNU Affero General Public License as 19 | * published by the Free Software Foundation, either version 3 of the 20 | * License, or (at your option) any later version. 21 | * 22 | * Commotion is distributed in the hope that it will be useful, 23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | * GNU Affero General Public License for more details. 26 | * 27 | * You should have received a copy of the GNU Affero General Public License 28 | * along with Commotion. If not, see . 29 | * 30 | * ===================================================================================== 31 | */ 32 | 33 | #ifndef _UTIL_H 34 | #define _UTIL_H 35 | #include 36 | #include 37 | 38 | #define NEW(O, T) O##_create(sizeof(T##_t), T##_proto) 39 | #define _(N) proto.N 40 | 41 | #define LOWERCASE(N) for ( ; *N; ++N) *N = tolower(*N); 42 | #define UPPERCASE(N) for ( ; *N; ++N) *N = toupper(*N); 43 | 44 | #define MAX_ARGS 16 45 | 46 | #define BSSID_SIZE 6 47 | #define BSSID_STR_SIZE 18 48 | #define ESSID_SIZE 32 49 | #define FREQ_SIZE 4 50 | #define CHAN_SIZE 2 51 | 52 | /** 53 | * @brief concatenates two strings 54 | * @param dst destination for new string 55 | * @param src string to be added to 56 | * @param size size of combined strings 57 | */ 58 | size_t strlcat(char *dst, const char *src, const size_t size); 59 | 60 | /** 61 | * @brief copies a string 62 | * @param dst destination for new string 63 | * @param src string to be copied 64 | * @param size size of string 65 | */ 66 | size_t strlcpy(char *dest, const char *src, const size_t size); 67 | 68 | /** 69 | * @brief prints output from string "str" in a specified format 70 | * @param str string to be printed 71 | * @param size size of string 72 | * @param format output format 73 | */ 74 | size_t snprintfcat(char *str, size_t size, const char *format, ...); 75 | 76 | /** 77 | * @brief removes white space from a given string (to parse for arguments) 78 | * @param s string to parse 79 | * @param out output from the string (with white space removed) 80 | * @param outlen length of the output 81 | */ 82 | size_t strstrip(const char *s, char *out, const size_t outlen); 83 | 84 | /** 85 | * @brief compares version numbers of two software releases 86 | * @param aver version number for software 'a' 87 | * @param bver version number for software 'b' 88 | */ 89 | int compare_version(const char * aver, const char *bver); 90 | 91 | typedef int (*file_iter)(const char* path, const char *filename); 92 | 93 | /** 94 | * @brief processes file paths 95 | * @param dir_path string of the directory path 96 | * @param loader number of directories in the file path 97 | */ 98 | int process_files(const char *dir_path, file_iter loader); 99 | 100 | /** 101 | * @brief parses a string and converts into a set of arguments 102 | * @param input the string to be parsed 103 | * @param argv pointer to argument list 104 | * @param argc number of arguments read from the string 105 | * @param max maximum length of string 106 | */ 107 | int string_to_argv(const char *input, char **argv, int *argc, const size_t max); 108 | 109 | /** 110 | * @brief converts argument vectors to a single string 111 | * @param argv pointer to argument list 112 | * @param argc number of arguments 113 | * @param output concatenated string of arguments 114 | * @param max maximum length of the string 115 | */ 116 | int argv_to_string(char **argv, const int argc, char *output, const size_t max); 117 | 118 | /** 119 | * @brief converts a MAC address from a string to individual bytes 120 | * @param macstr MAC string 121 | * @param mac an array for storing the MAC address 122 | */ 123 | void mac_string_to_bytes(char *macstr, unsigned char mac[6]); 124 | 125 | /** 126 | * @brief prints MAC address from MAC array 127 | * @param mac array storing MAC address 128 | */ 129 | void print_mac(unsigned char mac[6]); 130 | 131 | /** 132 | * @brief sets Wi-Fi frequency corresponding to specified channel 133 | * @param channel specified channel 134 | */ 135 | int wifi_freq(const int channel); 136 | 137 | /** 138 | * @brief sets Wi-Fi channel corresponding to specified freuency 139 | * @param frequency specified frequency 140 | */ 141 | int wifi_chan(const int frequency); 142 | 143 | /** 144 | * @brief generates a BSSID from hash of ESSID and channel 145 | * @param essid The ESSID to hash 146 | * @param channel an integer of the channel 147 | * @param bbsid The returned 6-byte BSSID 148 | */ 149 | void get_bssid(const char *essid, const unsigned int channel, char *bssid); 150 | 151 | /** 152 | * @brief prints a raw byte array in hex and ascii output 153 | * @param mem the byte array to print 154 | * @param len length of the byte array 155 | */ 156 | void hexdump(void *mem, unsigned int len); 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8) 2 | REMOVE_DEFINITIONS("--std=gnu99") 3 | PROJECT(gtest_builder C CXX) 4 | INCLUDE(ExternalProject) 5 | 6 | ExternalProject_Add(googletest 7 | SVN_REPOSITORY http://googletest.googlecode.com/svn/trunk 8 | CMAKE_ARGS -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=DebugLibs 9 | -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=ReleaseLibs 10 | -DCMAKE_CXX_FLAGS=${MSVC_COMPILER_DEFS} 11 | -Dgtest_force_shared_crt=ON 12 | PREFIX "${CMAKE_CURRENT_BINARY_DIR}" 13 | # Disable install step 14 | INSTALL_COMMAND "" 15 | ) 16 | 17 | # Specify include dir 18 | ExternalProject_Get_Property(googletest source_dir) 19 | SET(GTEST_INCLUDE_DIR ${source_dir}/include) 20 | 21 | # Specify MainTest's link libraries 22 | ExternalProject_Get_Property(googletest binary_dir) 23 | SET(GTEST_LIBRARY ${binary_dir}/libgtest.a) 24 | SET(GTEST_MAIN_LIBRARY ${binary_dir}/libgtest_main.a) 25 | 26 | #------------------- 27 | # Test 28 | #------------------- 29 | ENABLE_TESTING() 30 | INCLUDE(FindGTest QUIETLY) 31 | SET(PROJECT_TEST_NAME ${PROJECT_NAME_STR}_test) 32 | INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIR} ${COMMON_INCLUDES}) 33 | 34 | FILE(GLOB TEST_SRC_FILES ${PROJECT_SOURCE_DIR}/*.cpp) 35 | ADD_EXECUTABLE(${PROJECT_TEST_NAME} ${TEST_SRC_FILES}) 36 | ADD_DEPENDENCIES(${PROJECT_TEST_NAME} googletest) 37 | 38 | TARGET_LINK_LIBRARIES(${PROJECT_TEST_NAME} commotion) 39 | TARGET_LINK_LIBRARIES(${PROJECT_TEST_NAME} 40 | ${GTEST_LIBRARY} 41 | ${GTEST_MAIN_LIBRARY}) 42 | TARGET_LINK_LIBRARIES(${PROJECT_TEST_NAME} pthread) 43 | 44 | GTEST_ADD_TESTS(${PROJECT_TEST_NAME} "" ${TEST_SRC_FILES}) 45 | 46 | ADD_CUSTOM_COMMAND(TARGET ${PROJECT_TEST_NAME} POST_BUILD COMMAND ${PROJECT_TEST_NAME}) 47 | 48 | #get_cmake_property(_variableNames VARIABLES) 49 | #foreach (_variableName ${_variableNames}) 50 | # message(STATUS "${_variableName}=${${_variableName}}") 51 | #endforeach() 52 | -------------------------------------------------------------------------------- /tests/list.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file test.cpp 4 | * @brief 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 11/17/2013 06:01:11 PM 10 | * Compiler gcc/g++ 11 | * Organization The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Josh King 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published 18 | * by the Free Software Foundation, either version 3 of the License, 19 | * or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | extern "C" { 32 | #include "../src/obj.h" 33 | #include "../src/list.h" 34 | #include "../src/tree.h" 35 | } 36 | #include "gtest/gtest.h" 37 | 38 | class ListTest : public ::testing::Test 39 | { 40 | protected: 41 | co_obj_t *List16; 42 | co_obj_t *List32; 43 | void InsertObj(); 44 | void DeleteObj(); 45 | void Retrieval(); 46 | co_obj_t *TestString1; 47 | co_obj_t *TestString2; 48 | co_obj_t *TestString3; 49 | co_obj_t *TestString4; 50 | co_obj_t *TestString5; 51 | co_obj_t *TestString6; 52 | 53 | int ret; 54 | co_obj_t *ptr; 55 | 56 | ListTest() 57 | { 58 | List16 = co_list16_create(); 59 | List32 = co_list32_create(); 60 | 61 | TestString1 = co_bin8_create("1TESTVALUE1", 12, 0); 62 | TestString2 = co_bin8_create("2TESTVALUE2", 12, 0); 63 | TestString3 = co_bin8_create("3TESTVALUE3", 12, 0); 64 | TestString4 = co_bin8_create("4TESTVALUE4", 12, 0); 65 | TestString5 = co_bin8_create("5TESTVALUE5", 12, 0); 66 | TestString6 = co_bin8_create("6TESTVALUE6", 12, 0); 67 | 68 | ret = 0; 69 | ptr = NULL; 70 | } 71 | 72 | virtual void SetUp() 73 | { 74 | } 75 | 76 | ~ListTest() 77 | { 78 | co_obj_free(List16); 79 | co_obj_free(List32); 80 | } 81 | }; 82 | 83 | void ListTest::InsertObj() 84 | { 85 | ret = co_list_append(List16, TestString1); 86 | ASSERT_EQ(1, ret); 87 | 88 | ret = co_list_contains(List16, TestString1); 89 | ASSERT_EQ(1, ret); 90 | 91 | ret = co_list_append(List16, TestString2); 92 | ASSERT_EQ(1, ret); 93 | 94 | ret = co_list_contains(List16, TestString2); 95 | ASSERT_EQ(1, ret); 96 | 97 | // insert before 98 | ret = co_list_insert_before(List16, TestString3, TestString1); 99 | ASSERT_EQ(1, ret); 100 | 101 | ptr = co_list_get_first(List16); 102 | ASSERT_EQ(ptr, TestString3); 103 | 104 | // insert after 105 | ret = co_list_insert_after(List16, TestString4, TestString1); 106 | ASSERT_EQ(1, ret); 107 | 108 | ret = co_list_contains(List16, TestString4); 109 | ASSERT_EQ(1, ret); 110 | 111 | // append 112 | ret = co_list_append(List16, TestString5); 113 | ASSERT_EQ(1, ret); 114 | 115 | ptr = co_list_get_last(List16); 116 | ASSERT_EQ(ptr, TestString5); 117 | 118 | // prepend 119 | ret = co_list_prepend(List16, TestString6); 120 | ASSERT_EQ(1, ret); 121 | 122 | ptr = co_list_get_first(List16); 123 | ASSERT_EQ(ptr, TestString6); 124 | 125 | 126 | // repeat for List32 127 | ret = co_list_append(List32, TestString1); 128 | ASSERT_EQ(1, ret); 129 | 130 | ret = co_list_contains(List32, TestString1); 131 | ASSERT_EQ(1, ret); 132 | 133 | ret = co_list_append(List32, TestString2); 134 | ASSERT_EQ(1, ret); 135 | 136 | ret = co_list_contains(List32, TestString2); 137 | ASSERT_EQ(1, ret); 138 | 139 | // insert before 140 | ret = co_list_insert_before(List32, TestString3, TestString1); 141 | ASSERT_EQ(1, ret); 142 | 143 | ptr = co_list_get_first(List32); 144 | ASSERT_EQ(ptr, TestString3); 145 | 146 | // insert after 147 | ret = co_list_insert_after(List32, TestString4, TestString1); 148 | ASSERT_EQ(1, ret); 149 | 150 | ret = co_list_contains(List32, TestString4); 151 | ASSERT_EQ(1, ret); 152 | 153 | // append 154 | ret = co_list_append(List32, TestString5); 155 | ASSERT_EQ(1, ret); 156 | 157 | ptr = co_list_get_last(List32); 158 | ASSERT_EQ(ptr, TestString5); 159 | 160 | // prepend 161 | ret = co_list_prepend(List32, TestString6); 162 | ASSERT_EQ(1, ret); 163 | 164 | ptr = co_list_get_first(List32); 165 | ASSERT_EQ(ptr, TestString6); 166 | } 167 | 168 | void ListTest::DeleteObj() 169 | { 170 | ret = co_list_append(List16, TestString1); 171 | ASSERT_EQ(1, ret); 172 | 173 | co_obj_t *ptr = co_list_delete(List16, TestString1); 174 | ASSERT_EQ(TestString1, ptr); 175 | 176 | ret = co_list_append(List16, TestString2); 177 | ASSERT_EQ(1, ret); 178 | 179 | ptr = co_list_delete(List16, TestString2); 180 | ASSERT_EQ(TestString2, ptr); 181 | 182 | // confirm deletions 183 | ret = co_list_contains(List16, TestString1); 184 | ASSERT_EQ(0, ret); 185 | 186 | ret = co_list_contains(List16, TestString1); 187 | ASSERT_EQ(0, ret); 188 | 189 | 190 | // repeat for List32 191 | ret = co_list_append(List32, TestString1); 192 | ASSERT_EQ(1, ret); 193 | 194 | ptr = co_list_delete(List32, TestString1); 195 | ASSERT_EQ(TestString1, ptr); 196 | 197 | ret = co_list_append(List32, TestString2); 198 | ASSERT_EQ(1, ret); 199 | 200 | ptr = co_list_delete(List32, TestString2); 201 | ASSERT_EQ(TestString2, ptr); 202 | 203 | // confirm deletions 204 | ret = co_list_contains(List32, TestString1); 205 | ASSERT_EQ(0, ret); 206 | 207 | ret = co_list_contains(List32, TestString1); 208 | ASSERT_EQ(0, ret); 209 | } 210 | 211 | void ListTest::Retrieval() 212 | { 213 | ret = co_list_append(List16, TestString1); 214 | ASSERT_EQ(1, ret); 215 | 216 | ret = co_list_append(List16, TestString2); 217 | ASSERT_EQ(1, ret); 218 | 219 | ret = co_list_append(List16, TestString3); 220 | ASSERT_EQ(1, ret); 221 | 222 | // get list size 223 | ret = co_list_length(List16); 224 | ASSERT_EQ(3, ret); 225 | 226 | // get first node 227 | ptr = co_list_get_first(List16); 228 | ASSERT_EQ(TestString1, ptr); 229 | 230 | // get last node 231 | ptr = co_list_get_last(List16); 232 | ASSERT_EQ(TestString3, ptr); 233 | 234 | // get specific nodes 235 | ptr = co_list_element(List16, 1); 236 | ASSERT_EQ(TestString2, ptr); 237 | 238 | ptr = co_list_element(List16, 2); 239 | ASSERT_EQ(TestString3, ptr); 240 | 241 | 242 | // repeat for List32 243 | ret = co_list_append(List32, TestString1); 244 | ASSERT_EQ(1, ret); 245 | 246 | ret = co_list_append(List32, TestString2); 247 | ASSERT_EQ(1, ret); 248 | 249 | ret = co_list_append(List32, TestString3); 250 | ASSERT_EQ(1, ret); 251 | 252 | // get list size 253 | ret = co_list_length(List32); 254 | ASSERT_EQ(3, ret); 255 | 256 | // get first node 257 | ptr = co_list_get_first(List32); 258 | ASSERT_EQ(TestString1, ptr); 259 | 260 | // get last node 261 | ptr = co_list_get_last(List32); 262 | ASSERT_EQ(TestString3, ptr); 263 | 264 | // get specific nodes 265 | ptr = co_list_element(List32, 1); 266 | ASSERT_EQ(TestString2, ptr); 267 | 268 | ptr = co_list_element(List32, 2); 269 | ASSERT_EQ(TestString3, ptr); 270 | } 271 | 272 | 273 | 274 | 275 | TEST_F(ListTest, ListInsertTest) 276 | { 277 | InsertObj(); 278 | } 279 | 280 | TEST_F(ListTest, ListDeleteTest) 281 | { 282 | DeleteObj(); 283 | } 284 | 285 | TEST_F(ListTest, Retrieval) 286 | { 287 | Retrieval(); 288 | } -------------------------------------------------------------------------------- /tests/loop.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | extern "C" { 11 | #include "config.h" 12 | #include "debug.h" 13 | #include "util.h" 14 | #include "loop.h" 15 | #include "process.h" 16 | #include "profile.h" 17 | #include "socket.h" 18 | #include "msg.h" 19 | #include "iface.h" 20 | #include "id.h" 21 | } 22 | #include "gtest/gtest.h" 23 | 24 | extern co_socket_t unix_socket_proto; 25 | 26 | bool timer1_success = false; 27 | bool timer2_success = false; 28 | bool timer3_success = false; 29 | 30 | int timer1_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params); 31 | int timer2_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params); 32 | int timer3_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params); 33 | int loop_stop_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params); 34 | 35 | class LoopTest : public ::testing::Test 36 | { 37 | protected: 38 | int ret; 39 | 40 | // context pointers 41 | co_obj_t *context1; 42 | co_obj_t *context2; 43 | co_obj_t *context3; 44 | co_obj_t *stop; 45 | 46 | // time values 47 | struct timeval timeval1; 48 | struct timeval timeval2; 49 | struct timeval timeval3; 50 | struct timeval tv_stop; 51 | 52 | // tests 53 | void Timer(); 54 | void Socket(); 55 | 56 | LoopTest() 57 | { 58 | ret = co_loop_create(); 59 | // CHECK((poll_fd = epoll_create1(EPOLL_CLOEXEC)) != -1, "Failed to create epoll event."); 60 | } 61 | 62 | virtual void SetUp() 63 | { 64 | } 65 | 66 | ~LoopTest() 67 | { 68 | ret = co_loop_destroy(); 69 | } 70 | }; 71 | 72 | void LoopTest::Timer() 73 | { 74 | // intialize timer1 75 | co_obj_t *timer1 = co_timer_create(timeval1, timer1_cb, context1); 76 | ret = co_loop_set_timer(timer1, 1, context1); 77 | ASSERT_EQ(1, ret); 78 | 79 | // initialize timer2 80 | co_obj_t *timer2 = co_timer_create(timeval2, timer2_cb, context2); 81 | ret = co_loop_set_timer(timer2, 1, context1); 82 | ASSERT_EQ(1, ret); 83 | 84 | // initialize timer3 85 | co_obj_t *timer3 = co_timer_create(timeval3, timer3_cb, context3); 86 | ret = co_loop_set_timer(timer3, 1, context1); 87 | ASSERT_EQ(1, ret); 88 | 89 | // stops the loop (after 100 ms) 90 | co_obj_t *loop_stop = co_timer_create(tv_stop, loop_stop_cb, stop); 91 | ret = co_loop_set_timer(loop_stop, 100, stop); 92 | ASSERT_EQ(1, ret); 93 | 94 | co_loop_start(); 95 | 96 | EXPECT_TRUE(timer1_success); 97 | EXPECT_TRUE(timer2_success); 98 | EXPECT_TRUE(timer3_success); 99 | } 100 | 101 | void LoopTest::Socket() 102 | { 103 | // initialize socket and register it with the event loop 104 | co_socket_t *socket1 = (co_socket_t*)co_socket_create(sizeof(co_socket_t), unix_socket_proto); 105 | socket1->register_cb = co_loop_add_socket; 106 | socket1->bind((co_obj_t*)socket1, "commotiontest.sock"); 107 | 108 | co_obj_t *co_fd_create(co_obj_t *parent, int fd); 109 | 110 | // remove socket from loop 111 | ret = co_loop_remove_socket((co_obj_t *)socket1, NULL); 112 | ASSERT_EQ(1, ret); 113 | 114 | // destroy socket 115 | ret = co_socket_destroy((co_obj_t *)socket1); 116 | ASSERT_EQ(1, ret); 117 | } 118 | 119 | TEST_F(LoopTest, Timer) 120 | { 121 | Timer(); 122 | } 123 | 124 | TEST_F(LoopTest, Socket) 125 | { 126 | Socket(); 127 | } 128 | 129 | 130 | // callback functions 131 | int timer1_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params) 132 | { 133 | timer1_success = true; 134 | return 1; 135 | } 136 | 137 | int timer2_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params) 138 | { 139 | timer2_success = true; 140 | return 1; 141 | } 142 | 143 | int timer3_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params) 144 | { 145 | timer3_success = true; 146 | return 1; 147 | } 148 | 149 | // loop stop function (currently unused) 150 | int loop_stop_cb(co_obj_t *self, co_obj_t **output, co_obj_t *params) 151 | { 152 | co_loop_stop(); // breaks loop without returning 153 | return 1; 154 | } -------------------------------------------------------------------------------- /tests/msg.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "../src/obj.h" 3 | #include "../src/list.h" 4 | #include "../src/tree.h" 5 | #include "../src/msg.h" 6 | #include "../src/debug.h" 7 | } 8 | #include "gtest/gtest.h" 9 | 10 | 11 | static uint32_t _id = 0; 12 | 13 | static struct 14 | { 15 | uint8_t list_type; 16 | uint16_t list_len; 17 | uint8_t type_type; 18 | uint8_t type_value; 19 | uint8_t id_type; 20 | } _req_header = { 21 | .list_type = _list16, 22 | .list_len = 4, 23 | .type_type = _uint8, 24 | .type_value = 0, 25 | .id_type = _uint32 26 | }; 27 | 28 | #define REQUEST_MAX 4096 29 | #define RESPONSE_MAX 4096 30 | 31 | class MessageTest : public ::testing::Test 32 | { 33 | protected: 34 | // variables 35 | int ret = 0; 36 | size_t len = 0; 37 | char req[REQUEST_MAX]; 38 | char resp[RESPONSE_MAX]; 39 | char *method = "help"; 40 | size_t mlen = strlen(method) + 1; 41 | co_obj_t *m = co_str8_create(method, mlen, 0); 42 | size_t reqlen = 0; 43 | size_t importlen = 0; 44 | co_obj_t *param = co_list16_create(); 45 | co_obj_t *request = NULL; 46 | uint8_t *type = NULL; 47 | uint32_t *id = NULL; 48 | 49 | // functions 50 | void Request(); 51 | 52 | MessageTest() 53 | { 54 | } 55 | 56 | ~MessageTest() 57 | { 58 | } 59 | }; 60 | 61 | 62 | void MessageTest::Request() 63 | { 64 | // pack message 65 | reqlen = co_request_alloc(req, REQUEST_MAX, m, param); 66 | ASSERT_EQ(20, reqlen); 67 | 68 | DEBUG("\n\nNumber of bytes packed: %d\n\n", reqlen); 69 | 70 | // unpack message 71 | importlen = co_list_import(&request, req, reqlen); 72 | 73 | DEBUG("\n\nNumber of byes unpacked: %d\n\n", importlen); 74 | 75 | // check message contents 76 | co_obj_data((char **)&type, co_list_element(request, 0)); 77 | ASSERT_EQ(0, *type); 78 | 79 | ASSERT_EQ(sizeof(uint32_t), co_obj_data((char **)&id, co_list_element(request, 1))); 80 | } 81 | 82 | TEST_F (MessageTest, Request) 83 | { 84 | Request(); 85 | } -------------------------------------------------------------------------------- /tests/profile.cpp: -------------------------------------------------------------------------------- 1 | extern "C" { 2 | #include "../src/obj.h" 3 | #include "../src/list.h" 4 | #include "../src/tree.h" 5 | #include "../src/profile.h" 6 | } 7 | #include "gtest/gtest.h" 8 | 9 | SCHEMA(default) 10 | { 11 | SCHEMA_ADD("ssid", "commotionwireless.net"); 12 | SCHEMA_ADD("bssid", "02:CA:FF:EE:BA:BE"); 13 | SCHEMA_ADD("bssidgen", "true"); 14 | SCHEMA_ADD("channel", "5"); 15 | SCHEMA_ADD("mode", "adhoc"); 16 | SCHEMA_ADD("type", "mesh"); 17 | SCHEMA_ADD("dns", "208.67.222.222"); 18 | SCHEMA_ADD("domain", "mesh.local"); 19 | SCHEMA_ADD("ipgen", "true"); 20 | SCHEMA_ADD("ip", "100.64.0.0"); 21 | SCHEMA_ADD("netmask", "255.192.0.0"); 22 | SCHEMA_ADD("ipgenmask", "255.192.0.0"); 23 | SCHEMA_ADD("encryption", "psk2"); 24 | SCHEMA_ADD("key", "c0MM0t10n!r0cks"); 25 | SCHEMA_ADD("serval", "false"); 26 | SCHEMA_ADD("announce", "true"); 27 | return 1; 28 | } 29 | 30 | class ProfileTest : public ::testing::Test 31 | { 32 | protected: 33 | // test functions 34 | void Init(); 35 | void Add(); 36 | void Find(); 37 | void Remove(); 38 | void SetGet(); 39 | 40 | // variables 41 | int ret = 0; 42 | co_obj_t *profile1 = co_str8_create("profile1", 9, 0); 43 | co_obj_t *profile2 = co_str8_create("profile2", 9, 0); 44 | co_obj_t *found = NULL; 45 | 46 | // constructor 47 | ProfileTest() 48 | { 49 | ret = co_profiles_init(16); 50 | } 51 | 52 | virtual void SetUp() 53 | { 54 | } 55 | 56 | ~ProfileTest() 57 | { 58 | } 59 | }; 60 | 61 | void ProfileTest::Init() 62 | { 63 | ASSERT_EQ(1, ret); 64 | } 65 | 66 | void ProfileTest::Add() 67 | { 68 | ret = co_profile_add("profile1", 9); 69 | ASSERT_EQ(1, ret); 70 | } 71 | 72 | void ProfileTest::Find() 73 | { 74 | ret = co_profile_add("profile1", 9); 75 | ASSERT_EQ(1, ret); 76 | 77 | ret = co_profile_add("profile2", 9); 78 | ASSERT_EQ(1, ret); 79 | 80 | found = co_profile_find(profile1); 81 | ASSERT_TRUE(NULL != found); 82 | 83 | found = co_profile_find(profile2); 84 | ASSERT_TRUE(NULL != found); 85 | } 86 | 87 | void ProfileTest::Remove() 88 | { 89 | ret = co_profile_add("profile1", 9); 90 | ASSERT_EQ(1, ret); 91 | 92 | ret = co_profile_add("profile2", 9); 93 | ASSERT_EQ(1, ret); 94 | 95 | ret = co_profile_remove("profile1", 9); 96 | ASSERT_EQ(1, ret); 97 | 98 | // confirm removal 99 | found = co_profile_find(profile1); 100 | ASSERT_TRUE(NULL == found); 101 | 102 | ret = co_profile_remove("profile2", 9); 103 | ASSERT_EQ(1, ret); 104 | 105 | //confirm removal 106 | found = co_profile_find(profile2); 107 | ASSERT_TRUE(NULL == found); 108 | } 109 | 110 | void ProfileTest::SetGet() 111 | { 112 | SCHEMA_REGISTER(default); 113 | 114 | ret = co_profile_add("profile1", 9); 115 | ASSERT_EQ(1, ret); 116 | 117 | found = co_profile_find(profile1); 118 | ASSERT_TRUE(NULL != found); 119 | 120 | ret = co_profile_set_str((co_obj_t *)found, "ip", sizeof("ip"), "192.168.1.254", sizeof("192.168.1.254")); 121 | ASSERT_EQ(1, ret); 122 | 123 | char *ip; 124 | 125 | ret = co_profile_get_str(found, &ip, "ip", sizeof("ip")); 126 | ASSERT_STREQ("192.168.1.254", ip); 127 | } 128 | 129 | TEST_F(ProfileTest, Init) 130 | { 131 | Init(); 132 | } 133 | 134 | TEST_F(ProfileTest, Add) 135 | { 136 | Add(); 137 | } 138 | 139 | TEST_F(ProfileTest, Find) 140 | { 141 | Find(); 142 | } 143 | 144 | TEST_F(ProfileTest, Remove) 145 | { 146 | Remove(); 147 | } 148 | 149 | TEST_F(ProfileTest, SetGet) 150 | { 151 | SetGet(); 152 | } -------------------------------------------------------------------------------- /tests/scheduler.cpp.old: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | extern "C" { 11 | #include "config.h" 12 | #include "debug.h" 13 | #include "command.h" 14 | #include "util.h" 15 | #include "loop.h" 16 | #include "process.h" 17 | #include "profile.h" 18 | #include "socket.h" 19 | #include "msg.h" 20 | #include "olsrd.h" 21 | #include "iface.h" 22 | #include "id.h" 23 | } 24 | #include "gtest/gtest.h" 25 | 26 | extern co_timer_t co_timer_proto; 27 | 28 | static bool executed; 29 | static bool executed2; 30 | static bool executed3; 31 | static co_timer_t *timer_reset; 32 | static co_timer_t *timer_cancel; 33 | static int timer_callback(void *a, void *b); 34 | static int timer_callback2(void *a, void *b); 35 | static int timer_callback4(void *a, void *b); 36 | static int timer_callback5(void *a, void *b); 37 | static int timer_callback6(void *a, void *b); 38 | 39 | class SchedulerTests : public ::testing::Test { 40 | protected: 41 | SchedulerTests() { 42 | executed = false; 43 | executed2 = false; 44 | executed3 = false; 45 | co_loop_create(); 46 | } 47 | virtual ~SchedulerTests() { 48 | co_loop_destroy(); 49 | } 50 | }; 51 | 52 | static int timer_callback(void *a, void *b) { 53 | printf("callback\n"); 54 | executed = true; 55 | EXPECT_FALSE(executed2); 56 | return 1; 57 | } 58 | 59 | static int timer_callback2(void *a, void *b) { 60 | printf("callback2\n"); 61 | EXPECT_TRUE(executed); 62 | executed2 = true; 63 | co_loop_stop(); 64 | return 1; 65 | } 66 | 67 | static int timer_callback4(void *a, void *b) { 68 | printf("callback4\n"); 69 | co_loop_remove_timer(timer_cancel,(void*)NULL); 70 | co_loop_set_timer(timer_reset,999,(void*)NULL); 71 | executed = true; 72 | return 1; 73 | } 74 | 75 | static int timer_callback5(void *a, void *b) { 76 | printf("callback5\n"); 77 | executed2 = true; 78 | return 1; 79 | } 80 | 81 | static int timer_callback6(void *a, void *b) { 82 | printf("callback6\n"); 83 | executed3 = true; 84 | co_loop_stop(); 85 | return 1; 86 | } 87 | 88 | TEST_F(SchedulerTests, Scheduler) { 89 | co_timer_t *timer1 = NEW(co_timer,co_timer); 90 | co_timer_t *timer2 = NEW(co_timer,co_timer); 91 | timer1->timer_cb = timer_callback; 92 | timer2->timer_cb = timer_callback2; 93 | co_loop_set_timer(timer1,1000,(void*)NULL); 94 | co_loop_set_timer(timer2,1000,(void*)NULL); 95 | co_loop_start(); 96 | EXPECT_TRUE(executed); 97 | EXPECT_TRUE(executed2); 98 | free(timer1); 99 | free(timer2); 100 | } 101 | 102 | TEST_F(SchedulerTests, Scheduler2) { 103 | struct timespec ts; 104 | co_timer_t *timer1 = NEW(co_timer,co_timer); 105 | co_timer_t *timer2 = NEW(co_timer,co_timer); 106 | timer1->timer_cb = timer_callback; 107 | timer2->timer_cb = timer_callback2; 108 | clock_gettime(CLOCK_REALTIME, &ts); 109 | timer1->deadline = {ts.tv_sec + 6,1000}; 110 | co_loop_add_timer(timer1,NULL); 111 | co_loop_set_timer(timer2,7000,(void*)NULL); 112 | co_loop_start(); 113 | EXPECT_TRUE(executed); 114 | EXPECT_TRUE(executed2); 115 | free(timer1); 116 | free(timer2); 117 | } 118 | 119 | TEST_F(SchedulerTests, Scheduler3) { 120 | co_timer_t *timer1 = NEW(co_timer,co_timer); 121 | timer_cancel = NEW(co_timer,co_timer); 122 | timer_reset = NEW(co_timer,co_timer); 123 | timer1->timer_cb = timer_callback4; 124 | timer_cancel->timer_cb = timer_callback5; 125 | timer_reset->timer_cb = timer_callback6; 126 | co_loop_set_timer(timer1,1000,(void*)NULL); 127 | co_loop_set_timer(timer_cancel,2000,(void*)NULL); 128 | co_loop_set_timer(timer_reset,3000,(void*)NULL); 129 | co_loop_start(); 130 | EXPECT_TRUE(executed); 131 | EXPECT_FALSE(executed2); 132 | EXPECT_TRUE(executed3); 133 | free(timer1); 134 | free(timer_cancel); 135 | free(timer_reset); 136 | } 137 | 138 | TEST_F(SchedulerTests, Scheduler4) { 139 | co_timer_t *timer1 = NEW(co_timer,co_timer); 140 | timer1->timer_cb = timer_callback6; 141 | co_loop_set_timer(timer1,1000,(void*)NULL); 142 | EXPECT_FALSE(co_loop_add_timer(timer1,(void*)NULL)); 143 | co_loop_start(); 144 | EXPECT_TRUE(executed3); 145 | free(timer1); 146 | } 147 | 148 | int main(int argc, char **argv) { 149 | ::testing::InitGoogleTest(&argc, argv); 150 | return RUN_ALL_TESTS(); 151 | } 152 | -------------------------------------------------------------------------------- /tests/socket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | extern "C" { 11 | #include "config.h" 12 | #include "debug.h" 13 | #include "util.h" 14 | #include "loop.h" 15 | #include "process.h" 16 | #include "profile.h" 17 | #include "socket.h" 18 | #include "msg.h" 19 | #include "iface.h" 20 | #include "id.h" 21 | #include "list.h" 22 | } 23 | #include "gtest/gtest.h" 24 | 25 | extern co_socket_t unix_socket_proto; 26 | 27 | class SocketTest : public ::testing::Test 28 | { 29 | protected: 30 | int ret; 31 | 32 | void Create(); 33 | void SendReceive(); 34 | 35 | co_socket_t *socket1; 36 | co_socket_t *socket2; 37 | 38 | SocketTest() 39 | { 40 | socket1 = (co_socket_t*)co_socket_create(sizeof(co_socket_t), unix_socket_proto); 41 | socket1->bind((co_obj_t*)socket1, "commotiontest.sock"); 42 | 43 | socket2 = (co_socket_t*)co_socket_create(sizeof(co_socket_t), unix_socket_proto); 44 | socket2->connect((co_obj_t*)socket2, "commotiontest.sock"); 45 | } 46 | 47 | virtual void SetUp() 48 | { 49 | } 50 | 51 | ~SocketTest() 52 | { 53 | co_socket_destroy((co_obj_t *)socket1); 54 | } 55 | }; 56 | 57 | void SocketTest::Create() 58 | { 59 | ASSERT_TRUE(socket1); 60 | ASSERT_TRUE(socket2); 61 | } 62 | 63 | void SocketTest::SendReceive() 64 | { 65 | char buffer[13]; 66 | int length = 13; 67 | int received = 0; 68 | 69 | char test_message[13] = "test message"; 70 | 71 | ret = co_socket_send((co_obj_t *)socket2->fd, test_message, sizeof(test_message)); 72 | ASSERT_EQ(sizeof(test_message), ret); 73 | 74 | received = co_socket_receive((co_obj_t *)socket1, (co_obj_t *)socket1->fd, buffer, length); 75 | 76 | received = co_socket_receive((co_obj_t *)socket1, (co_obj_t *)co_list_get_first(socket1->rfd_lst), buffer, length); 77 | 78 | DEBUG("\n\nSent %d bytes.\n", ret); 79 | DEBUG("\n\nReceived %d bytes.\n", received); 80 | 81 | ASSERT_STREQ(test_message, buffer); 82 | } 83 | 84 | TEST_F(SocketTest, Create) 85 | { 86 | Create(); 87 | } 88 | 89 | TEST_F(SocketTest, SendReceive) 90 | { 91 | SendReceive(); 92 | } 93 | -------------------------------------------------------------------------------- /tests/tree-next.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file test.cpp 4 | * @brief 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 11/17/2013 06:01:11 PM 10 | * Compiler gcc/g++ 11 | * Organization The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Josh King 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published 18 | * by the Free Software Foundation, either version 3 of the License, 19 | * or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | extern "C" { 32 | #include "../src/obj.h" 33 | #include "../src/tree.h" 34 | } 35 | #include "gtest/gtest.h" 36 | 37 | class TreeNextTest : public ::testing::Test 38 | { 39 | protected: 40 | co_obj_t *tree16; 41 | co_obj_t *tree32; 42 | int strs_len = 40; 43 | char *strs[40] = { 44 | "bbbb", 45 | "bbba", 46 | "bbbc", 47 | "bbab", 48 | "bbaa", 49 | "bbac", 50 | "bbcb", 51 | "bbca", 52 | "bbcc", 53 | "abb", 54 | "aba", 55 | "abc", 56 | "aab", 57 | "aaa", 58 | "aac", 59 | "acb", 60 | "aca", 61 | "acc", 62 | "cbb", 63 | "cba", 64 | "cbc", 65 | "cab", 66 | "caa", 67 | "cac", 68 | "ccb", 69 | "cca", 70 | "ccc", 71 | "b", 72 | "bb", 73 | "bba", 74 | "bbb", 75 | "bbc", 76 | "a", 77 | "aa", 78 | "ab", 79 | "ac", 80 | "c", 81 | "ca", 82 | "cb", 83 | "cc" 84 | }; 85 | 86 | //tests 87 | void Test(); 88 | 89 | TreeNextTest() 90 | { 91 | tree16 = co_tree16_create(); 92 | tree32 = co_tree32_create(); 93 | 94 | for (int i = 0; i < strs_len; i++) { 95 | co_obj_t *str16 = co_str8_create(strs[i],strlen(strs[i]) + 1,0), 96 | *str32 = co_str8_create(strs[i],strlen(strs[i]) + 1,0); 97 | co_tree_insert(tree16,strs[i],strlen(strs[i]) + 1,str16); 98 | co_tree_insert(tree32,strs[i],strlen(strs[i]) + 1,str32); 99 | } 100 | } 101 | 102 | virtual void SetUp() 103 | { 104 | } 105 | 106 | ~TreeNextTest() 107 | { 108 | co_obj_free(tree16); 109 | co_obj_free(tree32); 110 | } 111 | }; 112 | 113 | /** 114 | * Compare strings alphabetically, used in qsort 115 | */ 116 | static int 117 | cmpstringp(const void *p1, const void *p2) 118 | { 119 | /* The actual arguments to this function are "pointers to 120 | * pointers to char", but strcmp(3) arguments are "pointers 121 | * to char", hence the following cast plus dereference */ 122 | return strcmp(* (char * const *) p1, * (char * const *) p2); 123 | } 124 | 125 | void TreeNextTest::Test() 126 | { 127 | co_obj_t *key = NULL; 128 | int i = 0; 129 | 130 | /* Sort test strings into alphabetical order */ 131 | qsort(strs,strs_len,sizeof(char*),cmpstringp); 132 | 133 | for (key = co_tree_next(tree16, NULL), i = 0; i < strs_len; key = co_tree_next(tree16, key), i++) { 134 | if (!key) 135 | co_tree_print(tree16); 136 | ASSERT_TRUE(key); 137 | EXPECT_STREQ(co_obj_data_ptr(key), strs[i]); 138 | co_obj_t *val = co_tree_find(tree16, strs[i], strlen(strs[i]) + 1); 139 | ASSERT_TRUE(val); 140 | EXPECT_STREQ(co_obj_data_ptr(val), strs[i]); 141 | } 142 | EXPECT_EQ(i,strs_len); 143 | 144 | for (key = co_tree_next(tree32, NULL), i = 0; i < strs_len; key = co_tree_next(tree32, key), i++) { 145 | if (!key) 146 | co_tree_print(tree32); 147 | ASSERT_TRUE(key); 148 | EXPECT_STREQ(co_obj_data_ptr(key), strs[i]); 149 | co_obj_t *val = co_tree_find(tree32, strs[i], strlen(strs[i]) + 1); 150 | ASSERT_TRUE(val); 151 | EXPECT_STREQ(co_obj_data_ptr(val), strs[i]); 152 | } 153 | EXPECT_EQ(i,strs_len); 154 | } 155 | 156 | TEST_F(TreeNextTest, TreeNextTest) 157 | { 158 | Test(); 159 | } 160 | -------------------------------------------------------------------------------- /tests/tree.cpp: -------------------------------------------------------------------------------- 1 | /* vim: set ts=2 expandtab: */ 2 | /** 3 | * @file test.cpp 4 | * @brief 5 | * 6 | * @author Josh King (jheretic), jking@chambana.net 7 | * 8 | * @internal 9 | * Created 11/17/2013 06:01:11 PM 10 | * Compiler gcc/g++ 11 | * Organization The Open Technology Institute 12 | * Copyright Copyright (c) 2013, Josh King 13 | * 14 | * This file is part of Commotion, Copyright (c) 2013, Josh King 15 | * 16 | * Commotion is free software: you can redistribute it and/or modify 17 | * it under the terms of the GNU General Public License as published 18 | * by the Free Software Foundation, either version 3 of the License, 19 | * or (at your option) any later version. 20 | * 21 | * Commotion is distributed in the hope that it will be useful, 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 24 | * GNU General Public License for more details. 25 | * 26 | * You should have received a copy of the GNU General Public License 27 | * along with Commotion. If not, see . 28 | * 29 | * ===================================================================================== 30 | */ 31 | extern "C" { 32 | #include "../src/obj.h" 33 | #include "../src/list.h" 34 | #include "../src/tree.h" 35 | } 36 | #include "gtest/gtest.h" 37 | 38 | /* 39 | * NOTE: Inserting keys with different length values will be 40 | * interpreted as different keys (eg insert("test", 5) and 41 | * insert("test", 6) are not the same and their values will be 42 | * stored in different nodes in the tree 43 | * 44 | * 45 | */ 46 | 47 | class TreeTest : public ::testing::Test 48 | { 49 | protected: 50 | co_obj_t *Tree16; 51 | co_obj_t *Tree32; 52 | void InsertObj(); 53 | void DeleteObj(); 54 | void UpdateObj(); 55 | co_obj_t *TestString1; 56 | co_obj_t *TestString2; 57 | co_obj_t *ReplaceString1; 58 | 59 | co_obj_t *TestString3; 60 | 61 | co_obj_t *ptr; 62 | int ret; 63 | 64 | TreeTest() 65 | { 66 | Tree16 = co_tree16_create(); 67 | Tree32 = co_tree32_create(); 68 | 69 | TestString1 = co_str8_create("1TESTVALUE1", 12, 0); 70 | TestString2 = co_str8_create("2TESTVALUE2", 12, 0); 71 | 72 | ReplaceString1 = co_str8_create("REPLACE", 9, 0); 73 | 74 | ret = 0; 75 | ptr = NULL; 76 | } 77 | 78 | virtual void SetUp() 79 | { 80 | } 81 | 82 | ~TreeTest() 83 | { 84 | co_obj_free(Tree16); 85 | co_obj_free(Tree32); 86 | } 87 | }; 88 | 89 | void TreeTest::InsertObj() 90 | { 91 | ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1); 92 | ASSERT_EQ(1, ret); 93 | 94 | ptr = co_tree_find(Tree16, "1TESTKEY1", 10); 95 | ASSERT_EQ(TestString1, ptr); 96 | 97 | ret = co_tree_insert(Tree16, "2TESTKEY2", 10, TestString2); 98 | ASSERT_EQ(1, ret); 99 | 100 | ptr = co_tree_find(Tree16, "2TESTKEY2", 10); 101 | ASSERT_EQ(TestString2, ptr); 102 | 103 | 104 | ret = co_tree_insert_force(Tree16, "1TESTKEY1", 10, ReplaceString1); 105 | ASSERT_EQ(1, ret); 106 | 107 | ptr = co_tree_find(Tree16, "1TESTKEY1", 10); 108 | ASSERT_EQ(ReplaceString1, ptr); 109 | 110 | 111 | // reinitialize TestString1 since it was freed by co_tree_insert_force() 112 | TestString1 = co_str8_create("1TESTVALUE1", 12, 0); 113 | 114 | // repeat for Tree 32 115 | ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1); 116 | ASSERT_EQ(1, ret); 117 | 118 | ptr = co_tree_find(Tree32, "1TESTKEY1", 10); 119 | ASSERT_EQ(TestString1, ptr); 120 | 121 | ret = co_tree_insert(Tree32, "2TESTKEY2", 10, TestString2); 122 | ASSERT_EQ(1, ret); 123 | 124 | ptr = co_tree_find(Tree32, "2TESTKEY2", 10); 125 | ASSERT_EQ(TestString2, ptr); 126 | 127 | 128 | ret = co_tree_insert_force(Tree32, "1TESTKEY1", 10, ReplaceString1); 129 | ASSERT_EQ(1, ret); 130 | 131 | ptr = co_tree_find(Tree32, "1TESTKEY1", 10); 132 | ASSERT_EQ(ReplaceString1, ptr); 133 | } 134 | 135 | void TreeTest::DeleteObj() 136 | { 137 | ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1); 138 | ASSERT_EQ(1, ret); 139 | 140 | ret = co_tree_insert(Tree16, "2TESTKEY2", 10, TestString2); 141 | ASSERT_EQ(1, ret); 142 | 143 | ptr = co_tree_delete(Tree16, "1TESTKEY1", 10); 144 | ASSERT_EQ(TestString1, ptr); 145 | 146 | ptr = co_tree_delete(Tree16, "2TESTKEY2", 10); 147 | ASSERT_EQ(TestString2, ptr); 148 | 149 | // confirm deletions 150 | ptr = co_tree_find(Tree16, "1TESTKEY1", 10); 151 | ASSERT_EQ(NULL, ptr); 152 | 153 | ptr = co_tree_find(Tree16, "2TESTKEY2", 10); 154 | ASSERT_EQ(NULL, ptr); 155 | 156 | 157 | // repeat for Tree32 158 | ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1); 159 | ASSERT_EQ(1, ret); 160 | 161 | ret = co_tree_insert(Tree32, "2TESTKEY2", 10, TestString2); 162 | ASSERT_EQ(1, ret); 163 | 164 | ptr = co_tree_delete(Tree32, "1TESTKEY1", 10); 165 | ASSERT_EQ(TestString1, ptr); 166 | 167 | ptr = co_tree_delete(Tree32, "2TESTKEY2", 10); 168 | ASSERT_EQ(TestString2, ptr); 169 | 170 | // confirm deletions 171 | ptr = co_tree_find(Tree32, "1TESTKEY1", 10); 172 | ASSERT_EQ(NULL, ptr); 173 | 174 | ptr = co_tree_find(Tree32, "2TESTKEY2", 10); 175 | ASSERT_EQ(NULL, ptr); 176 | } 177 | 178 | void TreeTest::UpdateObj() 179 | { 180 | ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1); 181 | ASSERT_EQ(1, ret); 182 | 183 | ret = co_tree_set_str(Tree16, "1TESTKEY1", 10, "REPLACE", 9); 184 | ASSERT_EQ(1, ret); 185 | 186 | ptr = co_tree_find(Tree16, "1TESTKEY1", 10); 187 | ASSERT_EQ(0, co_str_cmp(ptr, ReplaceString1)); 188 | 189 | // reinitialize TestString1 190 | TestString1 = co_str8_create("1TESTVALUE1", 12, 0); 191 | 192 | // repeat for Tree32 193 | ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1); 194 | ASSERT_EQ(1, ret); 195 | 196 | ret = co_tree_set_str(Tree32, "1TESTKEY1", 10, "REPLACE", 9); 197 | ASSERT_EQ(1, ret); 198 | 199 | ptr = co_tree_find(Tree32, "1TESTKEY1", 10); 200 | ASSERT_EQ(0, co_str_cmp(ptr, ReplaceString1)); 201 | } 202 | 203 | TEST_F(TreeTest, TreeInsertTest) 204 | { 205 | InsertObj(); 206 | } 207 | 208 | TEST_F(TreeTest, TreeDeleteTest) 209 | { 210 | DeleteObj(); 211 | } 212 | 213 | TEST_F(TreeTest, TreeUpdateTest) 214 | { 215 | UpdateObj(); 216 | } 217 | --------------------------------------------------------------------------------