From: Maksym Mamontov Date: Tue, 7 Jan 2020 17:35:08 +0000 (+0200) Subject: Port to CMake, get rid of os_int.h. X-Git-Url: https://git.stg.codes/stg.git/commitdiff_plain/46b0747592074017ff0ea4b33d4a7194235886e5 Port to CMake, get rid of os_int.h. --- diff --git a/.gitignore b/.gitignore index b49a31e2..ba791f70 100644 --- a/.gitignore +++ b/.gitignore @@ -1,29 +1,10 @@ -*.[ao] -*.d -*.so +build *.swp *.log *.diff *.patch *.vp* CVS* -make_tarball.sh -deps -projects/rscriptd/On* -projects/stargazer/On* -projects/stargazer/stargazer.conf -projects/stargazer/stargazer -projects/stargazer/rules -projects/stargazer/subnets -projects/stargazer/conf.d -projects/stargazer/var -stglibs/smtp.lib -stglibs/crypto.lib/blowfish.c -Makefile.conf -projects/convertor/convertor -projects/rscriptd/rscriptd -projects/sgconf/sgconf -projects/sgconf_xml/sgconf_xml doc/xmlrpc-doc/book doc/help/book doc/help/help.pdf diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..0872ec22 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,181 @@ +cmake_minimum_required (VERSION 3.1) + +set ( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules ) + +option ( BUILD_STG "Build Stargazer server." OFF ) +option ( BUILD_SGCONF "Build SGConf client." OFF ) +option ( BUILD_RSCRIPTD "Build RScriptD server." OFF ) +option ( BUILD_RLM_STG "Build rlm_stg FreeRADIUS module." OFF ) +option ( BUILD_SGAUTH "Build SGAuth client." OFF ) + +# General modules +option ( BUILD_MOD_AO "Build AlwaysOnline STG module." ON ) +option ( BUILD_MOD_IA "Buils InetAccess STG module." ON ) +option ( BUILD_MOD_SGCONFIG "Build SGConfig STG module." ON ) +option ( BUILD_MOD_PING "Build Ping STG module." ON ) +option ( BUILD_MOD_RSCRYPT "Build RScrypt STG module." ON ) +option ( BUILD_MOD_SMUX "Buils SMUX STG module." ON ) +option ( BUILD_MOD_STORE_FILES "Build file store STG module." ON ) +option ( BUILD_MOD_CAP_NF "Build NetFlow capture STG module." ON ) + +# OS-specific modules +option ( BUILD_MOD_CAP_ETHER_LINUX "Build Linux Ethernet capture STG module." OFF ) +option ( BUILD_MOD_CAP_ETHER_FREEBSD "Build FreeBSD Ethernet capture STG module." OFF ) +option ( BUILD_MOD_CAP_DIVERT "Build FreeBSD divert-socket capture STG MODULE." OFF ) + +# Lib-specific modules +option ( BUILD_MOD_STORE_FIREBIRD "Build Firebird store STG module." OFF ) +option ( BUILD_MOD_STORE_POSTGRESQL "Build PostgreSQL store STG module." OFF ) +option ( BUILD_MOD_STORE_MYSQL "Build MySQL store STG module." OFF ) +option ( BUILD_MOD_RPCCONFIG "Build XML-RPC configuretion STG module." OFF ) +option ( BUILD_MOD_CAP_PCAP "Build PCap capture STG module." OFF ) +option ( BUILD_MOD_CAP_NFQUEUE "Build NFQueue capture STG module." OFF ) +option ( BUILD_MOD_RADIUS "Build rlm_stg backend STG module." OFF ) + +option ( BUILD_ALL_MODS "Build all modules." OFF ) +option ( BUILD_ALL_LIBS "Build all libraries." OFF ) +option ( BUILD_TESTS "Build tests." OFF ) +option ( BUILD_ALL "Build binaries, libraries and tests." OFF ) +option ( ENABLE_COVERAGE "Enable code coverage analysis." OFF ) + +if ( BUILD_ALL ) + set ( BUILD_ALL_MODS ON ) + set ( BUILD_ALL_LIBS ON ) + set ( BUILD_TESTS ON ) + set ( BUILD_SGAUTH ON ) + set ( BUILD_RSCRIPTD ON ) + set ( BUILD_RLM_STG ON ) + set ( BUILD_SGCONF ON ) + set ( BUILD_STG ON ) +endif ( BUILD_ALL ) + +set ( BUILD_LIB_COMMON ON ) + +if ( BUILD_SGAUTH OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_CONFFILES ON ) + set ( BUILD_LIB_CRYPTO ON ) + set ( BUILD_LIB_IA ON ) +endif ( BUILD_SGAUTH OR BUILD_ALL_LIBS ) + +if ( BUILD_SGCONF OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_CRYPTO ON ) + set ( BUILD_LIB_SRVCONF ON ) +endif ( BUILD_SGCONF OR BUILD_ALL_LIBS ) + +if ( BUILD_RSCRIPTD OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_CONFFILES ON ) + set ( BUILD_LIB_CRYPTO ON ) + set ( BUILD_LIB_LOGGER ON ) + set ( BUILD_LIB_SCRIPTEXECUTER ON ) +endif ( BUILD_RSCRIPTD OR BUILD_ALL_LIBS ) + +if ( BUILD_RLM_STG OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_CRYPTO ON ) + set ( BUILD_LIB_JSON ON ) +endif ( BUILD_RLM_STG OR BUILD_ALL_LIBS ) + +if ( BUILD_STG OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_CONFFILES ON ) + set ( BUILD_LIB_CRYPTO ON ) + set ( BUILD_LIB_DOTCONFPP ON ) + set ( BUILD_LIB_LOGGER ON ) + set ( BUILD_LIB_SCRIPTEXECUTER ON ) + + # if ( BUILD_STG ) + # set ( BUILD_MOD_AO ON ) + # set ( BUILD_MOD_IA ON ) + # set ( BUILD_MOD_SGCONFIG ON ) + # set ( BUILD_MOD_PING ON ) + # set ( BUILD_MOD_RSCRYPT ON ) + # set ( BUILD_MOD_SMUX ON ) + # set ( BUILD_MOD_STORE_FILES ON ) + # set ( BUILD_MOD_CAP_NF ON ) + #endif ( BUILD_STG ) +endif ( BUILD_STG OR BUILD_ALL_LIBS ) + +if ( BUILD_ALL_MODS ) + set ( BUILD_MOD_STORE_FIREBIRD ON ) + set ( BUILD_MOD_STORE_MYSQL ON ) + set ( BUILD_MOD_STORE_POSTGRESQL ON ) + set ( BUILD_MOD_RPCCONFIG ON ) + set ( BUILD_MOD_CAP_PCAP ON ) + set ( BUILD_MOD_CAP_NFQUEUE ON ) + set ( BUILD_MOD_RADIUS ON ) +endif ( BUILD_ALL_MODS ) + +if ( BUILD_MOD_STORE_FIREBIRD OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_IBPP ON ) +endif ( BUILD_MOD_STORE_FIREBIRD OR BUILD_ALL_LIBS ) + +if ( BUILD_MOD_RADIUS OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_JSON ON ) + set ( BUILD_LIB_IBPP ON ) +endif ( BUILD_MOD_RADIUS OR BUILD_ALL_LIBS ) + +if ( BUILD_MOD_PING OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_PINGER ON ) +endif ( BUILD_MOD_PING OR BUILD_ALL_LIBS ) + +if ( BUILD_MOD_SMUX OR BUILD_ALL_LIBS ) + set ( BUILD_LIB_SMUX ON ) +endif ( BUILD_MOD_SMUX OR BUILD_ALL_LIBS ) + +enable_language (CXX) +set (CMAKE_CXX_STANDARD 17) +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wall -Wextra -Wshadow -Wlogical-op -Wuseless-cast -Wno-long-long -Wold-style-cast -Wstrict-aliasing -pedantic") + +if ( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" ) + add_definitions ( -DLINUX ) + set ( BUILD_MOD_CAP_ETHER_LINUX ON ) + if ( BUILD_LIB_IBPP ) + add_definitions ( -DIBPP_LINUX ) + endif ( BUILD_LIB_IBPP ) +elseif ( ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" ) + add_definitions ( -DFREE_BSD ) + set ( BUILD_MOD_CAP_ETHER_FREEBSD ON ) + set ( BUILD_MOD_CAP_DIVERT ON ) + if ( BUILD_LIB_IBPP ) + add_definitions ( -DIBPP_LINUX ) + message ( WARNING "IBPP does not support '${CMAKE_SYSTEM_NAME}'" ) + endif ( BUILD_LIB_IBPP ) +elseif ( ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" ) + add_definitions ( -DDARWIN ) + if ( BUILD_LIB_IBPP ) + add_definitions ( -DIBPP_DARWIN ) + endif ( BUILD_LIB_IBPP ) +else () + message ( WARNING "Unsupported system: '${CMAKE_SYSTEM_NAME}'" ) +endif () + +include_directories ( include ) + +#find_package ( OpenSSL 1.0.0 REQUIRED ) +#find_package ( Boost 1.66.0 REQUIRED COMPONENTS system unit_test_framework ) + +add_subdirectory ( libs ) + +if ( BUILD_RLM_STG ) + add_subdirectory ( rlm_stg ) +endif ( BUILD_RLM_STG ) + +if ( BUILD_RSCRIPTD ) + add_subdirectory ( rscriptd ) +endif ( BUILD_RSCRIPTD ) + +if ( BUILD_SGAUTH ) + add_subdirectory ( sgauth ) +endif ( BUILD_SGAUTH ) + +if ( BUILD_SGCONF ) + add_subdirectory ( sgconf ) +endif ( BUILD_SGCONF ) + +if ( BUILD_STG ) + add_subdirectory ( stargazer ) +endif ( BUILD_STG ) + +if ( BUILD_TESTS ) + add_subdirectory ( tests ) +endif ( BUILD_TESTS ) + +add_custom_target (cppcheck COMMAND cppcheck --enable=all --std=c++14 ${CMAKE_SOURCE_DIR}/rlm_stg ${CMAKE_SOURCE_DIR}/rscriptd ${CMAKE_SOURCE_DIR}/sgauth ${CMAKE_SOURCE_DIR}/sgconf ${CMAKE_SOURCE_DIR}/sgconv ${CMAKE_SOURCE_DIR}/stargazer) diff --git a/cmake/modules/FindFBClient.cmake b/cmake/modules/FindFBClient.cmake new file mode 100644 index 00000000..5199beff --- /dev/null +++ b/cmake/modules/FindFBClient.cmake @@ -0,0 +1,22 @@ +find_path ( FBClient_INCLUDE_DIR NAMES ibase.h DOC "Path to FBClient header files." ) +mark_as_advanced ( FBClient_INCLUDE_DIR ) + +find_library ( FBClient_LIB NAMES fbclient DOC "Location of FBClient library." ) +mark_as_advanced ( FBClient_LIB ) + +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args ( FBClient + REQUIRED_VARS FBClient_LIB FBClient_INCLUDE_DIR + VERSION_VAR FBClient_VERSION ) + +# Create the imported target +if ( FBClient_FOUND ) + set ( FBClient_INCLUDE_DIRS ${FBClient_INCLUDE_DIR} ) + set ( FBClient_LIBRARIES ${FBClient_LIB} ) + if ( NOT TARGET FBClient::FBClient ) + add_library ( FBClient::FBClient UNKNOWN IMPORTED ) + set_target_properties ( FBClient::FBClient PROPERTIES + IMPORTED_LOCATION "${FBClient_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${FBClient_INCLUDE_DIR}" ) + endif ( NOT TARGET FBClient::FBClient ) +endif ( FBClient_FOUND ) diff --git a/cmake/modules/FindMNL.cmake b/cmake/modules/FindMNL.cmake new file mode 100644 index 00000000..833f1bcd --- /dev/null +++ b/cmake/modules/FindMNL.cmake @@ -0,0 +1,22 @@ +find_path ( MNL_INCLUDE_DIR NAMES libmnl/libmnl.h DOC "Path to MNL header files." ) +mark_as_advanced ( MNL_INCLUDE_DIR ) + +find_library ( MNL_LIB NAMES mnl DOC "Location of MNL library." ) +mark_as_advanced ( MNL_LIB ) + +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args ( MNL + REQUIRED_VARS MNL_LIB MNL_INCLUDE_DIR + VERSION_VAR MNL_VERSION ) + +# Create the imported target +if ( MNL_FOUND ) + set ( MNL_INCLUDE_DIRS ${MNL_INCLUDE_DIR} ) + set ( MNL_LIBRARIES ${MNL_LIB} ) + if ( NOT TARGET MNL::MNL ) + add_library ( MNL::MNL UNKNOWN IMPORTED ) + set_target_properties ( MNL::MNL PROPERTIES + IMPORTED_LOCATION "${MNL_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${MNL_INCLUDE_DIR}" ) + endif ( NOT TARGET MNL::MNL ) +endif ( MNL_FOUND ) diff --git a/cmake/modules/FindMySQLConnector.cmake b/cmake/modules/FindMySQLConnector.cmake new file mode 100644 index 00000000..6ab31aea --- /dev/null +++ b/cmake/modules/FindMySQLConnector.cmake @@ -0,0 +1,32 @@ +find_path ( MySQLConnector_INCLUDE_DIR NAMES mysql/mysql.h mysql/mysql_version.h DOC "Path to MySQLConnector header files." ) +mark_as_advanced ( MySQLConnector_INCLUDE_DIR ) + +find_library ( MySQLConnector_LIB NAMES mysqlclient DOC "Location of MySQLConnector library." ) +mark_as_advanced ( MySQLConnector_LIB ) + +if ( MySQLConnector_INCLUDE_DIR ) + file ( READ "${MySQLConnector_INCLUDE_DIR}/mysql/mysql_version.h" ver ) + + string ( REGEX MATCH "LIBMYSQL_VERSION ([0-9]*)" _ ${ver} ) + + set ( MySQLConnector_VERSION ${CMAKE_MATCH_1} ) + + unset ( ver ) +endif ( MySQLConnector_INCLUDE_DIR ) + +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args ( MySQLConnector + REQUIRED_VARS MySQLConnector_LIB MySQLConnector_INCLUDE_DIR + VERSION_VAR MySQLConnector_VERSION ) + +# Create the imported target +if ( MySQLConnector_FOUND ) + set ( MySQLConnector_INCLUDE_DIRS ${MySQLConnector_INCLUDE_DIR} ) + set ( MySQLConnector_LIBRARIES ${MySQLConnector_LIB} ) + if ( NOT TARGET MySQL::Connector ) + add_library ( MySQL::Connector UNKNOWN IMPORTED ) + set_target_properties ( MySQL::Connector PROPERTIES + IMPORTED_LOCATION "${MySQLConnector_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${MySQLConnector_INCLUDE_DIR}" ) + endif ( NOT TARGET MySQL::Connector ) +endif ( MySQLConnector_FOUND ) diff --git a/cmake/modules/FindNFNetLink.cmake b/cmake/modules/FindNFNetLink.cmake new file mode 100644 index 00000000..7909cb05 --- /dev/null +++ b/cmake/modules/FindNFNetLink.cmake @@ -0,0 +1,22 @@ +find_path ( NFNetLink_INCLUDE_DIR NAMES libnfnetlink/libnfnetlink.h DOC "Path to NFNetLink header files." ) +mark_as_advanced ( NFNetLink_INCLUDE_DIR ) + +find_library ( NFNetLink_LIB NAMES nfnetlink DOC "Location of NFNetLink library." ) +mark_as_advanced ( NFNetLink_LIB ) + +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args ( NFNetLink + REQUIRED_VARS NFNetLink_LIB NFNetLink_INCLUDE_DIR + VERSION_VAR NFNetLink_VERSION ) + +# Create the imported target +if ( NFNetLink_FOUND ) + set ( NFNetLink_INCLUDE_DIRS ${NFNetLink_INCLUDE_DIR} ) + set ( NFNetLink_LIBRARIES ${NFNetLink_LIB} ) + if ( NOT TARGET NF::NetLink ) + add_library ( NF::NetLink UNKNOWN IMPORTED ) + set_target_properties ( NF::NetLink PROPERTIES + IMPORTED_LOCATION "${NFNetLink_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${NFNetLink_INCLUDE_DIR}" ) + endif ( NOT TARGET NF::NetLink ) +endif ( NFNetLink_FOUND ) diff --git a/cmake/modules/FindNFQueue.cmake b/cmake/modules/FindNFQueue.cmake new file mode 100644 index 00000000..b05e61b8 --- /dev/null +++ b/cmake/modules/FindNFQueue.cmake @@ -0,0 +1,22 @@ +find_path ( NFQueue_INCLUDE_DIR NAMES libnetfilter_queue/libnetfilter_queue.h DOC "Path to NFQueue header files." ) +mark_as_advanced ( NFQueue_INCLUDE_DIR ) + +find_library ( NFQueue_LIB NAMES netfilter_queue DOC "Location of NFQueue library." ) +mark_as_advanced ( NFQueue_LIB ) + +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args ( NFQueue + REQUIRED_VARS NFQueue_LIB NFQueue_INCLUDE_DIR + VERSION_VAR NFQueue_VERSION ) + +# Create the imported target +if ( NFQueue_FOUND ) + set ( NFQueue_INCLUDE_DIRS ${NFQueue_INCLUDE_DIR} ) + set ( NFQueue_LIBRARIES ${NFQueue_LIB} ) + if ( NOT TARGET NF::Queue ) + add_library ( NF::Queue UNKNOWN IMPORTED ) + set_target_properties ( NF::Queue PROPERTIES + IMPORTED_LOCATION "${NFQueue_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${NFQueue_INCLUDE_DIR}" ) + endif ( NOT TARGET NF::Queue ) +endif ( NFQueue_FOUND ) diff --git a/cmake/modules/FindPCap.cmake b/cmake/modules/FindPCap.cmake new file mode 100644 index 00000000..d1dff55a --- /dev/null +++ b/cmake/modules/FindPCap.cmake @@ -0,0 +1,38 @@ +find_path ( PCap_INCLUDE_DIR NAMES pcap.h pcap/pcap.h DOC "Path to PCap header files." ) +mark_as_advanced ( PCap_INCLUDE_DIR ) + +find_library ( PCap_LIB NAMES pcap DOC "Location of PCap library." ) +mark_as_advanced ( PCap_LIB ) + +if ( PCap_INCLUDE_DIR ) + file ( READ "${PCap_INCLUDE_DIR}/pcap/pcap.h" ver ) + + string ( REGEX MATCH "PCAP_VERSION_MAJOR ([0-9]*)" _ ${ver} ) + set ( ver_major ${CMAKE_MATCH_1} ) + + string ( REGEX MATCH "PCAP_VERSION_MINOR ([0-9]*)" _ ${ver} ) + set ( ver_minor ${CMAKE_MATCH_1} ) + + set ( PCap_VERSION "${ver_major}.${ver_minor}" ) + + unset ( ver ) + unset ( ver_major ) + unset ( ver_minor ) +endif ( PCap_INCLUDE_DIR ) + +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args ( PCap + REQUIRED_VARS PCap_LIB PCap_INCLUDE_DIR + VERSION_VAR PCap_VERSION ) + +# Create the imported target +if ( PCap_FOUND ) + set ( PCap_INCLUDE_DIRS ${PCap_INCLUDE_DIR} ) + set ( PCap_LIBRARIES ${PCap_LIB} ) + if ( NOT TARGET PCap::PCap ) + add_library ( PCap::PCap UNKNOWN IMPORTED ) + set_target_properties ( PCap::PCap PROPERTIES + IMPORTED_LOCATION "${PCap_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${PCap_INCLUDE_DIR}" ) + endif ( NOT TARGET PCap::PCap ) +endif ( PCap_FOUND ) diff --git a/cmake/modules/FindYAJL.cmake b/cmake/modules/FindYAJL.cmake new file mode 100644 index 00000000..2e18caf0 --- /dev/null +++ b/cmake/modules/FindYAJL.cmake @@ -0,0 +1,42 @@ +find_path ( YAJL_INCLUDE_DIR NAMES yajl/yajl_parse.h yajl/yajl_version.h DOC "Path to YAJL header files." ) +mark_as_advanced ( YAJL_INCLUDE_DIR ) + +find_library ( YAJL_LIB NAMES yajl DOC "Location of YAJL library." ) +mark_as_advanced ( YAJL_LIB ) + +if ( YAJL_INCLUDE_DIR ) + file ( READ "${YAJL_INCLUDE_DIR}/yajl/yajl_version.h" ver ) + + string ( REGEX MATCH "YAJL_MAJOR ([0-9]*)" _ ${ver} ) + set ( ver_major ${CMAKE_MATCH_1} ) + + string ( REGEX MATCH "YAJL_MINOR ([0-9]*)" _ ${ver} ) + set ( ver_minor ${CMAKE_MATCH_1} ) + + string ( REGEX MATCH "YAJL_MICRO ([0-9]*)" _ ${ver} ) + set ( ver_micro ${CMAKE_MATCH_1} ) + + set ( YAJL_VERSION "${ver_major}.${ver_minor}.${ver_micro}" ) + + unset ( ver ) + unset ( ver_major ) + unset ( ver_minor ) + unset ( ver_micro ) +endif ( YAJL_INCLUDE_DIR ) + +include ( FindPackageHandleStandardArgs ) +find_package_handle_standard_args ( YAJL + REQUIRED_VARS YAJL_LIB YAJL_INCLUDE_DIR + VERSION_VAR YAJL_VERSION ) + +# Create the imported target +if ( YAJL_FOUND ) + set ( YAJL_INCLUDE_DIRS ${YAJL_INCLUDE_DIR} ) + set ( YAJL_LIBRARIES ${YAJL_LIB} ) + if ( NOT TARGET YAJL::YAJL ) + add_library ( YAJL::YAJL UNKNOWN IMPORTED ) + set_target_properties ( YAJL::YAJL PROPERTIES + IMPORTED_LOCATION "${YAJL_LIB}" + INTERFACE_INCLUDE_DIRECTORIES "${YAJL_INCLUDE_DIR}" ) + endif ( NOT TARGET YAJL::YAJL ) +endif ( YAJL_FOUND ) diff --git a/include/stg/admin.h b/include/stg/admin.h index 961968a1..f3851291 100644 --- a/include/stg/admin.h +++ b/include/stg/admin.h @@ -22,9 +22,9 @@ #define ADMIN_H #include +#include #include "admin_conf.h" -#include "os_int.h" class ADMIN { public: diff --git a/include/stg/admin_conf.h b/include/stg/admin_conf.h index 6f8005f5..88d944bf 100644 --- a/include/stg/admin_conf.h +++ b/include/stg/admin_conf.h @@ -11,7 +11,7 @@ #include -#include "os_int.h" +#include #define ADM_LOGIN_LEN (32) #define ADM_PASSWD_LEN (32) diff --git a/include/stg/ia_packets.h b/include/stg/ia_packets.h index 3520270c..afc014c6 100644 --- a/include/stg/ia_packets.h +++ b/include/stg/ia_packets.h @@ -1,7 +1,7 @@ #ifndef PACKETH #define PACKETH -#include "os_int.h" +#include #define CONN_SYN_N 0 #define CONN_SYN_ACK_N 1 diff --git a/include/stg/message.h b/include/stg/message.h index 5a0e918e..49f8c7c6 100644 --- a/include/stg/message.h +++ b/include/stg/message.h @@ -11,10 +11,9 @@ */ #include +#include #include -#include "os_int.h" - //----------------------------------------------------------------------------- struct STG_MSG_HDR { diff --git a/include/stg/os_int.h b/include/stg/os_int.h deleted file mode 100644 index 00ab3fad..00000000 --- a/include/stg/os_int.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - */ - - /* - $Revision: 1.4 $ - $Date: 2008/03/25 17:41:50 $ - */ - - -#ifndef OS_INT_H -#define OS_INT_H - -#ifdef LINUX -#include -#endif - -#if defined(FREE_BSD5) || defined(DARWIN) -#include -#endif - -#ifdef FREE_BSD -#include -#endif - -#ifdef WIN32 - -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; - -typedef int int32_t; -typedef unsigned int uint32_t; - -typedef short int int16_t; -typedef short unsigned int uint16_t; - -typedef char int8_t; -typedef unsigned char uint8_t; - - -#endif - - -#endif - diff --git a/include/stg/plugin.h b/include/stg/plugin.h index 2deabcc3..d02ff699 100644 --- a/include/stg/plugin.h +++ b/include/stg/plugin.h @@ -29,9 +29,9 @@ #define PLUGIN_H #include +#include #include "noncopyable.h" -#include "os_int.h" #include "admins.h" #include "users.h" #include "tariffs.h" diff --git a/include/stg/rad_packets.h b/include/stg/rad_packets.h index 96cddc4b..90ed9298 100644 --- a/include/stg/rad_packets.h +++ b/include/stg/rad_packets.h @@ -23,7 +23,7 @@ #define RAD_ID "00100" -#include "os_int.h" +#include struct RAD_PACKET { diff --git a/include/stg/raw_ip_packet.h b/include/stg/raw_ip_packet.h index b94faf86..30e1c8fe 100644 --- a/include/stg/raw_ip_packet.h +++ b/include/stg/raw_ip_packet.h @@ -1,7 +1,7 @@ #ifndef RAW_IP_PACKET_H #define RAW_IP_PACKET_H -#if defined(FREE_BSD) || defined(FREE_BSD5) +#if defined(FREE_BSD) #include // n_long in netinet/ip.h #endif diff --git a/include/stg/rs_packets.h b/include/stg/rs_packets.h index 503fe91d..0c31e228 100644 --- a/include/stg/rs_packets.h +++ b/include/stg/rs_packets.h @@ -34,7 +34,7 @@ #define RS_ID "RSP00" -#include "os_int.h" +#include namespace RS { diff --git a/include/stg/service_conf.h b/include/stg/service_conf.h index b6c24490..a9b8d5c4 100644 --- a/include/stg/service_conf.h +++ b/include/stg/service_conf.h @@ -22,9 +22,9 @@ #define SERVICE_CONF_H #include "resetable.h" -#include "os_int.h" #include +#include struct SERVICE_CONF { diff --git a/include/stg/tariff.h b/include/stg/tariff.h index 4f5b4166..6f9d8767 100644 --- a/include/stg/tariff.h +++ b/include/stg/tariff.h @@ -21,12 +21,11 @@ #ifndef TARIFF_H #define TARIFF_H -#include "os_int.h" - #include +#include #include #include -#include +#include struct TARIFF_DATA; diff --git a/include/stg/user.h b/include/stg/user.h index 7772a298..654f3344 100644 --- a/include/stg/user.h +++ b/include/stg/user.h @@ -25,12 +25,12 @@ #include "message.h" #include "tariff.h" #include "user_traff.h" -#include "os_int.h" #include #include #include +#include class USER_PROPERTIES; class AUTH; diff --git a/include/stg/user_conf.h b/include/stg/user_conf.h index a16b3929..d48682d6 100644 --- a/include/stg/user_conf.h +++ b/include/stg/user_conf.h @@ -9,10 +9,10 @@ #include #include +#include #include "const.h" #include "user_ips.h" #include "resetable.h" -#include "os_int.h" //----------------------------------------------------------------------------- struct USER_CONF diff --git a/include/stg/user_ips.h b/include/stg/user_ips.h index bb920957..ee227e5d 100644 --- a/include/stg/user_ips.h +++ b/include/stg/user_ips.h @@ -28,9 +28,9 @@ #define USER_IPS_H #include "stg/common.h" -#include "os_int.h" #include +#include #include #include #include diff --git a/include/stg/user_stat.h b/include/stg/user_stat.h index ff020dc7..4cedb591 100644 --- a/include/stg/user_stat.h +++ b/include/stg/user_stat.h @@ -28,11 +28,11 @@ #define USER_STAT_H #include +#include #include #include #include -#include "os_int.h" #include "resetable.h" #include "user_traff.h" //----------------------------------------------------------------------------- diff --git a/include/stg/user_traff.h b/include/stg/user_traff.h index 3ca9768e..5abcee33 100644 --- a/include/stg/user_traff.h +++ b/include/stg/user_traff.h @@ -29,10 +29,10 @@ #include "resetable.h" #include "const.h" -#include "os_int.h" #include #include +#include enum TRAFF_DIRECTION {TRAFF_UPLOAD, TRAFF_DOWNLOAD}; diff --git a/lib/.placeholder b/lib/.placeholder deleted file mode 100644 index e69de29b..00000000 diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt new file mode 100644 index 00000000..af3d944f --- /dev/null +++ b/libs/CMakeLists.txt @@ -0,0 +1,49 @@ +set ( CMAKE_POSITION_INDEPENDENT_CODE ON ) + +if ( BUILD_LIB_COMMON ) + add_subdirectory (common) +endif ( BUILD_LIB_COMMON ) + +if ( BUILD_LIB_CONFFILES ) + add_subdirectory (conffiles) +endif ( BUILD_LIB_CONFFILES ) + +if ( BUILD_LIB_CRYPTO ) + add_subdirectory (crypto) +endif ( BUILD_LIB_CRYPTO ) + +if ( BUILD_LIB_DOTCONFPP ) + add_subdirectory (dotconfpp) +endif ( BUILD_LIB_DOTCONFPP ) + +if ( BUILD_LIB_IA ) + add_subdirectory (ia) +endif ( BUILD_LIB_IA ) + +if ( BUILD_LIB_IBPP ) + add_subdirectory (ibpp) +endif ( BUILD_LIB_IBPP ) + +if ( BUILD_LIB_JSON ) + add_subdirectory (json) +endif ( BUILD_LIB_JSON ) + +if ( BUILD_LIB_LOGGER ) + add_subdirectory (logger) +endif ( BUILD_LIB_LOGGER ) + +if ( BUILD_LIB_PINGER ) + add_subdirectory (pinger) +endif ( BUILD_LIB_PINGER ) + +if ( BUILD_LIB_SCRIPTEXECUTER ) + add_subdirectory (scriptexecuter) +endif ( BUILD_LIB_SCRIPTEXECUTER ) + +if ( BUILD_LIB_SMUX ) + add_subdirectory (smux) +endif ( BUILD_LIB_SMUX ) + +if ( BUILD_LIB_SRVCONF ) + add_subdirectory (srvconf) +endif ( BUILD_LIB_SRVCONF ) diff --git a/libs/common/CMakeLists.txt b/libs/common/CMakeLists.txt new file mode 100644 index 00000000..330ee0d6 --- /dev/null +++ b/libs/common/CMakeLists.txt @@ -0,0 +1,7 @@ +set ( CPP_FILES blockio.cpp common.cpp strptime.cpp ) + +include_directories ( include ) + +add_library ( common STATIC ${CPP_FILES} ) + +target_include_directories ( common PUBLIC include ) diff --git a/libs/common/Makefile b/libs/common/Makefile new file mode 100644 index 00000000..932e2709 --- /dev/null +++ b/libs/common/Makefile @@ -0,0 +1,18 @@ +############################################################################### +# $Id: Makefile,v 1.9 2010/01/21 13:02:12 faust Exp $ +############################################################################### + +include ../../Makefile.conf + +LIB_NAME = stgcommon + +SRCS = common.cpp \ + strptime.cpp \ + blockio.cpp + +INCS = common.h \ + blockio.h + +LIBS += $(LIBICONV) + +include ../Makefile.in diff --git a/libs/common/blockio.cpp b/libs/common/blockio.cpp new file mode 100644 index 00000000..04fd1d81 --- /dev/null +++ b/libs/common/blockio.cpp @@ -0,0 +1,102 @@ +#include "stg/blockio.h" + +namespace +{ + +void* adjust(void* base, size_t shift) +{ + char* ptr = static_cast(base); + return ptr + shift; +} + +} // namspace anonymous + +using STG::BlockReader; +using STG::BlockWriter; + +BlockReader::BlockReader(const IOVec& ioVec) + : m_dest(ioVec), + m_remainder(0) +{ + for (size_t i = 0; i < m_dest.size(); ++i) + m_remainder += m_dest[i].iov_len; +} + +bool BlockReader::read(int socket) +{ + if (m_remainder == 0) + return true; + + size_t offset = m_dest.size() - 1; + size_t toRead = m_remainder; + while (offset > 0) { + if (toRead < m_dest[offset].iov_len) + break; + toRead -= m_dest[offset].iov_len; + --offset; + } + + IOVec dest(m_dest.size() - offset); + for (size_t i = 0; i < dest.size(); ++i) { + if (i == 0) { + dest[0].iov_len = toRead; + dest[0].iov_base = adjust(m_dest[offset].iov_base, m_dest[offset].iov_len - toRead); + } else { + dest[i] = m_dest[offset + i]; + } + } + + ssize_t res = readv(socket, dest.data(), dest.size()); + if (res < 0) + return false; + if (res == 0) + return m_remainder == 0; + if (res < static_cast(m_remainder)) + m_remainder -= res; + else + m_remainder = 0; + return true; +} + +BlockWriter::BlockWriter(const IOVec& ioVec) + : m_source(ioVec), + m_remainder(0) +{ + for (size_t i = 0; i < m_source.size(); ++i) + m_remainder += m_source[i].iov_len; +} + +bool BlockWriter::write(int socket) +{ + if (m_remainder == 0) + return true; + + size_t offset = m_source.size() - 1; + size_t toWrite = m_remainder; + while (offset > 0) { + if (toWrite < m_source[offset].iov_len) + break; + toWrite -= m_source[offset].iov_len; + --offset; + } + + IOVec source(m_source.size() - offset); + for (size_t i = 0; i < source.size(); ++i) { + if (i == 0) { + source[0].iov_len = toWrite; + source[0].iov_base = adjust(m_source[offset].iov_base, m_source[offset].iov_len - toWrite); + } else { + source[i] = m_source[offset + i]; + } + } + ssize_t res = writev(socket, source.data(), source.size()); + if (res < 0) + return false; + if (res == 0) + return m_remainder == 0; + if (res < static_cast(m_remainder)) + m_remainder -= res; + else + m_remainder = 0; + return true; +} diff --git a/libs/common/common.cpp b/libs/common/common.cpp new file mode 100644 index 00000000..8cfcf402 --- /dev/null +++ b/libs/common/common.cpp @@ -0,0 +1,1165 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Date: 27.10.2002 + */ + +/* + * Author : Boris Mikhailenko + */ + + /* + $Revision: 1.42 $ + $Date: 2010/11/08 10:11:19 $ + $Author: faust $ + */ + +// For old and dub systems +// Like FreeBSD4 +#include +#include +#include +#include + +#include + +#ifdef WIN32 +#include +#else +#include +#include +#include +#include +#endif + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "stg/common.h" + +#ifndef INET_ADDRSTRLEN +# define INET_ADDRSTRLEN 16 +#endif + +namespace +{ +//--------------------------------------------------------------------------- +unsigned char koi2win[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xB8, 0xBA, 0xA5, 0xB3, 0xBF, + 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xB4, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xA8, 0xAA, 0xB5, 0xB2, 0xAF, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xA5, 0xBE, 0xBF, + 0xFE, 0xE0, 0xE1, 0xF6, 0xE4, 0xE5, 0xF4, 0xE3, + 0xF5, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, + 0xEF, 0xFF, 0xF0, 0xF1, 0xF2, 0xF3, 0xE6, 0xE2, + 0xFC, 0xFB, 0xE7, 0xF8, 0xFD, 0xF9, 0xF7, 0xFA, + 0xDE, 0xC0, 0xC1, 0xD6, 0xC4, 0xC5, 0xD4, 0xC3, + 0xD5, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, + 0xCF, 0xDF, 0xD0, 0xD1, 0xD2, 0xD3, 0xC6, 0xC2, + 0xDC, 0xDB, 0xC7, 0xD8, 0xDD, 0xD9, 0xD7, 0xDA}; + + +unsigned char win2koi[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xBD, 0xA6, 0xA7, + 0xB3, 0xA9, 0xB4, 0xAB, 0xAC, 0xAD, 0xAE, 0xB7, + 0xB0, 0xB1, 0xB6, 0xA6, 0xAD, 0xB5, 0xB6, 0xB7, + 0xA3, 0xB9, 0xA4, 0xBB, 0xBC, 0xBD, 0xBE, 0xA7, + 0xE1, 0xE2, 0xF7, 0xE7, 0xE4, 0xE5, 0xF6, 0xFA, + 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0, + 0xF2, 0xF3, 0xF4, 0xF5, 0xE6, 0xE8, 0xE3, 0xFE, + 0xFB, 0xFD, 0xFF, 0xF9, 0xF8, 0xFC, 0xE0, 0xF1, + 0xC1, 0xC2, 0xD7, 0xC7, 0xC4, 0xC5, 0xD6, 0xDA, + 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, + 0xD2, 0xD3, 0xD4, 0xD5, 0xC6, 0xC8, 0xC3, 0xDE, + 0xDB, 0xDD, 0xDF, 0xD9, 0xD8, 0xDC, 0xC0, 0xD1}; +} + +#ifdef WIN32 +//----------------------------------------------------------------------------- +const char * inet_ntop(int af, const void * src, char * dst, unsigned long length) +{ +struct sockaddr_in addr; +addr.sin_family = af; +addr.sin_port = 0; +memcpy(&addr.sin_addr.s_addr, src, sizeof(addr.sin_addr.s_addr)); +if (WSAAddressToStringA(reinterpret_cast(&addr), sizeof(addr), 0, dst, &length)) + { + return NULL; + } +return dst; +} +//----------------------------------------------------------------------------- +int inet_pton(int af, const char * src, void * dst) +{ +// Fuck you Microsoft! +// Why the hell not to use const char *? +size_t slen = strlen(src); +char * buf = new char[slen + 1]; +strncpy(buf, src, slen + 1); +buf[slen] = 0; +struct sockaddr_in addr; +addr.sin_family = af; +addr.sin_port = 0; +addr.sin_addr.s_addr = 0; +int length = sizeof(addr); +if (WSAStringToAddressA(buf, af, 0, reinterpret_cast(&addr), &length)) + { + delete[] buf; + return -1; + } +memcpy(dst, &addr, sizeof(addr)); +delete[] buf; +return 1; +} +#endif +//----------------------------------------------------------------------------- +int strtodouble2(const char * s, double &a) +{ +char *res; + +a = strtod(s, &res); + +if (*res != 0) + return EINVAL; + +return 0; +} +//----------------------------------------------------------------------------- +#ifdef DEBUG +int printfd(const char * __file__, const char * fmt, ...) +#else +int printfd(const char *, const char *, ...) +#endif +{ +#ifdef DEBUG +char buff[1024]; + +time_t t = time(NULL); + +va_list vl; +va_start(vl, fmt); +vsnprintf(buff, sizeof(buff), fmt, vl); +va_end(vl); + +printf("%18s > %s > ", __file__, LogDate(t)+11); +printf("%s", buff); + +#endif +return 0; +} +//----------------------------------------------------------------------------- +int strprintf(std::string * str, const char * fmt, ...) +{ +char buff[1024]; + +va_list vl; +va_start(vl, fmt); +int n = vsnprintf(buff, sizeof(buff), fmt, vl); +va_end(vl); +buff[1023] = 0; +*str = buff; + +return n; +} +//----------------------------------------------------------------------------- +const char *IntToKMG(int64_t a, int stat) +{ +static const double K = 1024; +static const double M = 1024 * 1024; +static const double G = 1024 * 1024 * 1024; +static char str[30]; +double value = a; + +switch (stat) + { + case ST_B: + #ifdef __WIN32__ + sprintf(str, "%Ld", a); + #else + sprintf(str, "%lld", a); + #endif + break; + case ST_KB: + sprintf(str, "%.2f kb", value / K); + break; + case ST_MB: + sprintf(str, "%.2f Mb", value / M); + break; + default: + if (a > G) + { + sprintf(str, "%.2f Gb", value / G); + return &str[0]; + } + if (a < -G) + { + sprintf(str, "%.2f Gb", value / G); + return &str[0]; + } + if (a > M) + { + sprintf(str, "%.2f Mb", value / M); + return &str[0]; + } + if (a < -M) + { + sprintf(str, "%.2f Mb", value / M); + return &str[0]; + } + + sprintf(str, "%.2f kb", value / K); + break; + } +return str; +} +//--------------------------------------------------------------------------- +void KOIToWin(const char * s1, char * s2, int l) +{ +for (int j = 0; j < l; j++) + { + unsigned char t = s1[j]; + s2[j] = koi2win[t]; + + if (s1[j] == 0) + break; + } +} +//--------------------------------------------------------------------------- +void WinToKOI(const char * s1, char * s2, int l) +{ +for (int j = 0; j < l; j++) + { + unsigned char t = s1[j]; + s2[j] = win2koi[t]; + + if (s1[j] == 0) + break; + } +} +//--------------------------------------------------------------------------- +void KOIToWin(const std::string & s1, std::string * s2) +{ +s2->erase(s2->begin(), s2->end()); +s2->reserve(s1.length()); +for (size_t j = 0; j < s1.length(); j++) + { + unsigned char t = s1[j]; + s2->push_back(koi2win[t]); + } +} +//--------------------------------------------------------------------------- +void WinToKOI(const std::string & s1, std::string * s2) +{ +s2->erase(s2->begin(), s2->end()); +s2->reserve(s1.length()); +for (size_t j = 0; j < s1.length(); j++) + { + unsigned char t = s1[j]; + s2->push_back(win2koi[t]); + } +} +//--------------------------------------------------------------------------- +void Encode12str(std::string & dst, const std::string & src) +{ +dst.erase(dst.begin(), dst.end()); +for (size_t i = 0; i < src.length(); i++) + { + dst.push_back('a' + (src[i] & 0x0f)); + dst.push_back('a' + ((src[i] & 0xf0) >> 4)); + } +} +//--------------------------------------------------------------------------- +void Decode21str(std::string & dst, const std::string & src) +{ +dst.erase(dst.begin(), dst.end()); +for (size_t i = 0; i < src.length() / 2; i++) + { + char c1 = src[i * 2]; + char c2 = src[i * 2 + 1]; + + c1 -= 'a'; + c2 -= 'a'; + + dst.push_back(static_cast(c1 + (c2 << 4))); + } +} +//--------------------------------------------------------------------------- +void Encode12(char * dst, const char * src, size_t srcLen) +{ +for (size_t i = 0; i <= srcLen; i++) + { + char c1 = src[i] & 0x0f; + char c2 = (src[i] & 0xf0) >> 4; + + c1 += 'a'; + c2 += 'a'; + + dst[i * 2] = c1; + dst[i * 2 + 1] = c2; + } +dst[srcLen * 2] = 0; +} +//--------------------------------------------------------------------------- +void Decode21(char * dst, const char * src) +{ +for (size_t i = 0; ; i++) + { + if (src[i * 2] == 0) + break; + + char c1 = src[i * 2]; + char c2 = src[i * 2 + 1]; + + c1 -= 'a'; + c2 -= 'a'; + + dst[i] = static_cast(c1 + (c2 << 4)); + } +dst[strlen(src) / 2] = 0; +} +//--------------------------------------------------------------------------- +int ParseIPString(const char * str, uint32_t * ips, int maxIP) +{ +/* + *Function Name:ParseIPString + * + *Parameters: + ÓÔÒÏËÁ ÄÌÑ ÒÁÚÂÏÒÁ É ÍÁÓÓÉ× ËÕÄÁ ÚÁÎÏÓÉÔØ ÐÏÌÕÞÅÎÎÙÅ ÁÄÒÅÓÁ + * + *Description: + îÁ ×ÈÏÄÅ ÄÏÌÖÎÁ ÂÙÔØ ÓÔÒÏËÁ ×ÉÄÁ "ip1,ip2,ip3" ÉÌÉ "*" + ÷ ÐÅÒ×ÏÍ ÓÌÕÞÁÅ × ÍÁÓÓÉ× ÚÁÎÏÓÑÔÓÑ ÒÁÚÏÂÒÁÎÎÙÅ ÁÄÒÅÓÁ. + åÓÌÉ ÉÈ ÍÅÎØÛÅ MAX_IP?, ÔÏ ÐÏÓÌÅÄÎÉÊ ÁÄÒÅÓ ÂÕÄÅÔ 255.255.255.255 + åÓÌÉ ÓÔÒÏËÁ * , ÔÏ ÐÅÒ×ÁÙÊ ÁÄÒÅÓ ÂÕÄÅÔ 0.0.0.0, Ô.Å. ÌÀÂÏÊ + * + *Returns: 0 ÅÓÌÉ ×ÓÅ ïë + * + */ + +char p[255]; +int n = 0; + +strncpy(p, str, 254); +char * pp = p; + +memset(ips, 0xFF, sizeof(unsigned long) * maxIP); + +if (str[0] == '*' && strlen(str) == 1) + { + ips[0] = 0; + return 0; + } + +for (int i = 0; i < maxIP; i++) + { + char * p1 = strtok(pp, ",\n "); + pp = NULL; + + if (p1 == NULL && n == 0)// ÕËÁÚÁÔÅÌØ ÎÕÌØ É ÐÒÏÞÉÔÁÎÏ ÁÄÒÅÓÏ× ÔÏÖÅ ÎÏÌØ + { + return EINVAL; + } + + if (p1 == NULL && n) + { + return 0; + } + + struct in_addr in; + if (inet_pton(AF_INET, p1, &in) != 1) + { + //printf("INADDR_NONE\n"); + return EINVAL; + } + + ips[n] = in.s_addr; + + /*if (ips[n] == INADDR_NONE) + return EINVAL;*/ + + n++; + + if (n >= maxIP) + return 0; + + } + +return 0; +} +//----------------------------------------------------------------------------- +int DaysInCurrentMonth() +{ +time_t t = time(NULL); + +struct tm * lt = localtime(&t); + +return DaysInMonth(lt->tm_year, lt->tm_mon); +} +//----------------------------------------------------------------------------- +int DaysInMonth(unsigned year, unsigned mon) +{ +assert(mon < 12 && "Month number should be 0 - 11"); +switch (mon) + { + case 0: return 31; //jan + case 1: + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) + return 29; + return 28; //feb + case 2: return 31; //mar + case 3: return 30; //apr + case 4: return 31; //may + case 5: return 30; //june + case 6: return 31; //jule + case 7: return 31; //aug + case 8: return 30; //sep + case 9: return 31; //oct + case 10: return 30; //nov + case 11: return 31; //dec + } +return -1; // We will never reach here +} +//----------------------------------------------------------------------------- +int Min8(int a) +{ +/* +æÕÎËÃÉÑ ×ÏÚ×ÒÁÝÁÅÔ ÎÁÉÍÅÎØÛÅÅ ÞÉÓÌÏ ËÒÁÔÎÏÅ 8-ÍÉ ÂÏÌØÛÅÅ ÉÌÉ ÒÁ×ÎÏÅ ÚÁÄÁÎÎÏÍÕ + * */ +if (a % 8 == 0) + return a; + +return a + (8 - a % 8); +} +//----------------------------------------------------------------------------- +/*char * inet_ntostr(unsigned long ip) +{ +struct in_addr addr = {ip}; +return inet_ntoa(addr); +}*/ +//----------------------------------------------------------------------------- +std::string inet_ntostring(uint32_t ip) +{ + char buf[INET_ADDRSTRLEN + 1]; + return inet_ntop(AF_INET, &ip, buf, INET_ADDRSTRLEN); +} +//----------------------------------------------------------------------------- +uint32_t inet_strington(const std::string & value) +{ + uint32_t result; + + if (inet_pton(AF_INET, value.c_str(), &result) <= 0) + return 0; + + return result; +} +//----------------------------------------------------------------------------- +std::string TimeToString(time_t time) +{ +struct tm brokenTime; + +brokenTime.tm_wday = 0; +brokenTime.tm_yday = 0; +brokenTime.tm_isdst = 0; + +gmtime_r(&time, &brokenTime); + +char buf[32]; +strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime); + +return buf; +} +//----------------------------------------------------------------------------- +int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2) +{ +char hs1[10], ms1[10], hs2[10], ms2[10]; +char s1[25], s2[25]; +char ss[49]; +char *p1, *p2; + +strncpy(ss, str, 48); + +p1 = strtok(ss, "-"); +if (!p1) + return -1; + +strncpy(s1, p1, 24); + +p2 = strtok(NULL, "-"); +if (!p2) + return -1; + +strncpy(s2, p2, 24); + +p1 = strtok(s1, ":"); +if (!p1) + return -1; + +strncpy(hs1, p1, 9); + +p2 = strtok(NULL, ":"); +if (!p2) + return -1; + +strncpy(ms1, p2, 9); + +p1 = strtok(s2, ":"); +if (!p1) + return -1; + +strncpy(hs2, p1, 9); + +p2 = strtok(NULL, ":"); +if (!p2) + return -1; + +strncpy(ms2, p2, 9); + +if (str2x(hs1, h1) != 0) + return -1; + +if (str2x(ms1, m1) != 0) + return -1; + +if (str2x(hs2, h2) != 0) + return -1; + +if (str2x(ms2, m2) != 0) + return -1; + +return 0; +} +/*//--------------------------------------------------------------------------- +bool IsDigit(char c) +{ +if (c >= '0' && c <= '9') + return true; +return false; +} +//----------------------------------------------------------------------------- +bool IsAlpha(char c) +{ +if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) + return true; +return false; +}*/ +//----------------------------------------------------------------------------- +const char * LogDate(time_t t) +{ +static char s[32]; +struct tm * tt = localtime(&t); + +snprintf(s, 20, "%d-%s%d-%s%d %s%d:%s%d:%s%d", + tt->tm_year + 1900, + tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1, + tt->tm_mday < 10 ? "0" : "", tt->tm_mday, + tt->tm_hour < 10 ? "0" : "", tt->tm_hour, + tt->tm_min < 10 ? "0" : "", tt->tm_min, + tt->tm_sec < 10 ? "0" : "", tt->tm_sec); + +return s; +} +//----------------------------------------------------------------------------- +uint32_t CalcMask(uint32_t msk) +{ +if (msk >= 32) return 0xFFffFFff; +if (msk == 0) return 0; +return htonl(0xFFffFFff << (32 - msk)); +} +//--------------------------------------------------------------------------- +void TouchFile(const std::string & fileName) +{ +FILE * f = fopen(fileName.c_str(), "w"); +if (f) + fclose(f); +} +//--------------------------------------------------------------------------- +#ifdef WIN32 +void EncodeStr(char * str, unsigned long serial, int useHDD) +{ +int len = strlen(str); +char stren[100]; +int i, j = 0; +char c1, c2; +char serial_c[sizeof(serial)]; +memcpy(serial_c, &serial, sizeof(serial)); + +for (i = 0; i < len; i++) + { + if (!useHDD) + str[i] = str[i]^49; + else + { + str[i] = str[i]^serial_c[j%sizeof(serial)]; + j++; + } + } + +for (i = 0; i < 2*len; i++) + { + if (i%2) + { + c1 = (str[i/2] >> 4); + c1 = c1 + 50; + stren[i] = c1; + } + else + { + c2 = (str[i/2] & 0x0f); + c2 += 50; + stren[i] = c2; + } + } +stren[i] = 0; +strcpy(str, stren); +} +//--------------------------------------------------------------------------- +void DecodeStr(char * str, unsigned long serial, int useHDD) +{ +size_t len = strlen(str); +char strdc[100]; +char serial_c[sizeof(serial)]; +memcpy(serial_c, &serial, sizeof(serial)); + +for (size_t i = 0; i < len; i += 2) + { + char c1 = (str[i] - 50); + char c2 = (str[i+1] - 50)<<4; + strdc[i/2] = c1+c2; + } +for (size_t i = 0; i < len/2; i++) + { + if (!useHDD) + strdc[i] = strdc[i]^49; + else + { + strdc[i] = strdc[i]^serial_c[j%sizeof(serial)]; + j++; + } + } +strdc[i] = 0; +strcpy(str, strdc); +} +//--------------------------------------------------------------------------- +#endif //WIN32 +void SwapBytes(uint16_t & value) +{ + value = static_cast((value >> 8) | + (value << 8)); +} +//--------------------------------------------------------------------------- +void SwapBytes(uint32_t & value) +{ + value = static_cast((value >> 24) | + ((value << 8) & 0x00FF0000L) | + ((value >> 8) & 0x0000FF00L) | + (value << 24)); +} +//--------------------------------------------------------------------------- +void SwapBytes(uint64_t & value) +{ + value = static_cast((value >> 56) | + ((value << 40) & 0x00FF000000000000LL) | + ((value << 24) & 0x0000FF0000000000LL) | + ((value << 8) & 0x000000FF00000000LL) | + ((value >> 8) & 0x00000000FF000000LL) | + ((value >> 24) & 0x0000000000FF0000LL) | + ((value >> 40) & 0x000000000000FF00LL) | + (value << 56)); +} +//--------------------------------------------------------------------------- +void SwapBytes(int16_t & value) +{ + uint16_t temp = value; + SwapBytes(temp); + value = temp; +} +//--------------------------------------------------------------------------- +void SwapBytes(int32_t & value) +{ + uint32_t temp = value; + SwapBytes(temp); + value = temp; +} +//--------------------------------------------------------------------------- +void SwapBytes(int64_t & value) +{ + uint64_t temp = value; + SwapBytes(temp); + value = temp; +} +//--------------------------------------------------------------------------- +std::string formatTime(time_t ts) +{ +char buf[32]; +struct tm brokenTime; + +brokenTime.tm_wday = 0; +brokenTime.tm_yday = 0; +brokenTime.tm_isdst = 0; + +gmtime_r(&ts, &brokenTime); + +strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime); + +return buf; +} +//--------------------------------------------------------------------------- +time_t readTime(const std::string & ts) +{ +if (ts == "0000-00-00 00:00:00") + return 0; + +struct tm brokenTime; + +brokenTime.tm_wday = 0; +brokenTime.tm_yday = 0; +brokenTime.tm_isdst = 0; + +stg_strptime(ts.c_str(), "%Y-%m-%d %H:%M:%S", &brokenTime); + +return stg_timegm(&brokenTime); +} +//--------------------------------------------------------------------------- +int str2x(const std::string & str, int32_t & x) +{ +x = static_cast(strtol(str.c_str(), NULL, 10)); + +if (errno == ERANGE) + return -1; + +return 0; +} +//--------------------------------------------------------------------------- +int str2x(const std::string & str, uint32_t & x) +{ +x = static_cast(strtoul(str.c_str(), NULL, 10)); + +if (errno == ERANGE) + return -1; + +return 0; +} +#ifndef WIN32 +//--------------------------------------------------------------------------- +int str2x(const std::string & str, int64_t & x) +{ +x = strtoll(str.c_str(), NULL, 10); + +if (errno == ERANGE) + return -1; + +return 0; +} +//--------------------------------------------------------------------------- +int str2x(const std::string & str, uint64_t & x) +{ +x = strtoull(str.c_str(), NULL, 10); + +if (errno == ERANGE) + return -1; + +return 0; +} +#endif +//--------------------------------------------------------------------------- +const std::string & x2str(uint32_t x, std::string & s) +{ +return unsigned2str(x, s); +} +//--------------------------------------------------------------------------- +const std::string & x2str(uint64_t x, std::string & s) +{ +return unsigned2str(x, s); +} +//--------------------------------------------------------------------------- +const std::string & x2str(double x, std::string & s) +{ +char buf[256]; +snprintf(buf, sizeof(buf), "%f", x); +s = buf; +return s; +} +//--------------------------------------------------------------------------- +std::string & TrimL(std::string & val) +{ +size_t pos = val.find_first_not_of(" \t"); +if (pos == std::string::npos) + { + val.erase(val.begin(), val.end()); + } +else + { + val.erase(0, pos); + } +return val; +} +//--------------------------------------------------------------------------- +std::string & TrimR(std::string & val) +{ +size_t pos = val.find_last_not_of(" \t"); +if (pos != std::string::npos) + { + val.erase(pos + 1); + } +return val; +} +//--------------------------------------------------------------------------- +std::string & Trim(std::string & val) +{ +return TrimR(TrimL(val)); +} +//--------------------------------------------------------------------------- +std::string Trim(const std::string & val) +{ +std::string res(val); +return TrimR(TrimL(res)); +} +//--------------------------------------------------------------------------- +std::string ToLower(std::string value) +{ + std::transform(value.begin(), value.end(), value.begin(), ::tolower); + return value; +} +//--------------------------------------------------------------------------- +std::string ToUpper(std::string value) +{ + std::transform(value.begin(), value.end(), value.begin(), ::toupper); + return value; +} +//--------------------------------------------------------------------------- +#ifdef WIN32 +static int is_leap(unsigned y) +{ + y += 1900; + return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); +} +#endif +//--------------------------------------------------------------------------- + +time_t stg_timegm(struct tm * brokenTime) +{ +#ifdef WIN32 +static const unsigned ndays[2][12] ={ + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; +time_t res = 0; +for (int i = 70; i < brokenTime->tm_year; ++i) + res += is_leap(i) ? 366 : 365; +for (int i = 0; i < brokenTime->tm_mon; ++i) + res += ndays[is_leap(brokenTime->tm_year)][i]; +res += brokenTime->tm_mday - 1; +res *= 24; +res += brokenTime->tm_hour; +res *= 60; +res += brokenTime->tm_min; +res *= 60; +res += brokenTime->tm_sec; +return res; +#else +#ifdef HAVE_TIMEGM +return timegm(brokenTime); +#else +time_t ret; +char *tz; +tz = getenv("TZ"); +setenv("TZ", "", 1); +tzset(); +ret = mktime(brokenTime); +if (tz) + setenv("TZ", tz, 1); +else + unsetenv("TZ"); +tzset(); +return ret; +#endif // HAVE_TIMEGM +#endif // WIN32 +} +//--------------------------------------------------------------------------- +std::string IconvString(const std::string & source, + const std::string & from, + const std::string & to) +{ +if (source.empty()) + return std::string(); + +size_t inBytesLeft = source.length() + 1; +size_t outBytesLeft = source.length() * 2 + 1; + +char * inBuf = new char[inBytesLeft]; +char * outBuf = new char[outBytesLeft]; + +strncpy(inBuf, source.c_str(), source.length()); + +inBuf[source.length()] = 0; + +#if defined(CONST_ICONV) +const char * srcPos = inBuf; +#else +char * srcPos = inBuf; +#endif +char * dstPos = outBuf; + +iconv_t handle = iconv_open(to.c_str(), + from.c_str()); + +if (handle == iconv_t(-1)) + { + if (errno == EINVAL) + { + printfd(__FILE__, "IconvString(): iconv from %s to %s failed\n", from.c_str(), to.c_str()); + delete[] outBuf; + delete[] inBuf; + return source; + } + else + printfd(__FILE__, "IconvString(): iconv_open error\n"); + + delete[] outBuf; + delete[] inBuf; + return source; + } + +size_t res = iconv(handle, + &srcPos, &inBytesLeft, + &dstPos, &outBytesLeft); + +if (res == size_t(-1)) + { + printfd(__FILE__, "IconvString(): '%s'\n", strerror(errno)); + + iconv_close(handle); + delete[] outBuf; + delete[] inBuf; + return source; + } + +dstPos = 0; + +std::string dst(outBuf); + +iconv_close(handle); + +delete[] outBuf; +delete[] inBuf; + +return dst; +} + +int ParseYesNo(const std::string & str, bool * val) +{ +if (0 == strncasecmp(str.c_str(), "yes", 3)) + { + *val = true; + return 0; + } + +if (0 == strncasecmp(str.c_str(), "no", 2)) + { + *val = false; + return 0; + } + +return -1; +} + +int ParseInt(const std::string & str, int * val) +{ +if (str2x(str, *val)) + return -1; +return 0; +} + +int ParseUnsigned(const std::string & str, unsigned * val) +{ +if (str2x(str, *val)) + return -1; +return 0; +} + +int ParseIntInRange(const std::string & str, int min, int max, int * val) +{ +if (ParseInt(str, val) != 0) + return -1; + +if (*val < min || *val > max) + return -1; + +return 0; +} + +int ParseUnsignedInRange(const std::string & str, unsigned min, + unsigned max, unsigned * val) +{ +if (ParseUnsigned(str, val) != 0) + return -1; + +if (*val < min || *val > max) + return -1; + +return 0; +} + +bool WaitPackets(int sd) +{ +fd_set rfds; +FD_ZERO(&rfds); +FD_SET(sd, &rfds); + +struct timeval tv; +tv.tv_sec = 0; +tv.tv_usec = 500000; + +int res = select(sd + 1, &rfds, NULL, NULL, &tv); +if (res == -1) // Error + { + if (errno != EINTR) + printfd(__FILE__, "Error on select: '%s'\n", strerror(errno)); + return false; + } + +if (res == 0) // Timeout + return false; + +return true; +} + +bool ReadAll(int sd, void * dest, size_t size) +{ +size_t done = 0; +char * ptr = static_cast(dest); +while (done < size) + { + if (!WaitPackets(sd)) + return false; + ssize_t res = read(sd, ptr + done, size - done); + if (res < 0) + return false; + if (res == 0) + return true; + done += res; + } +return true; +} + +bool WriteAll(int sd, const void * source, size_t size) +{ +size_t done = 0; +const char * ptr = static_cast(source); +while (done < size) + { + ssize_t res = write(sd, ptr + done, size - done); + if (res <= 0) + return false; + done += res; + } +return true; +} + +std::string ToPrintable(const std::string & src) +{ + std::string dest; + + for (size_t i = 0; i < src.size(); ++i) + if (std::isprint(src[i])) + dest += src[i]; + else + dest += "\\" + x2str(src[i]); + + return dest; +} + +uid_t str2uid(const std::string& name) +{ + const passwd* res = getpwnam(name.c_str()); + if (res == NULL) + return -1; + return res->pw_uid; +} + +gid_t str2gid(const std::string& name) +{ + const group* res = getgrnam(name.c_str()); + if (res == NULL) + return -1; + return res->gr_gid; +} + +mode_t str2mode(const std::string& name) +{ + if (name.length() < 3 || name.length() > 4) + return -1; + + if (name.length() == 4 && name[0] != '0') + return -1; + + mode_t res = 0; + for (size_t i = 0; i < name.length(); ++i) + { + if (name[i] > '7' || name[i] < '0') + return -1; + res = (res << 3) + (name[i] - '0'); + } + return res; +} diff --git a/libs/common/include/stg/blockio.h b/libs/common/include/stg/blockio.h new file mode 100644 index 00000000..3879e39e --- /dev/null +++ b/libs/common/include/stg/blockio.h @@ -0,0 +1,43 @@ +#ifndef __STG_STGLIBS_BLOCK_IO_H__ +#define __STG_STGLIBS_BLOCK_IO_H__ + +#include + +#include + +namespace STG +{ + +typedef std::vector IOVec; + +class BlockReader +{ + public: + BlockReader(const IOVec& ioVec); + + bool read(int socket); + bool done() const { return m_remainder == 0; } + size_t remainder() const { return m_remainder; } + + private: + IOVec m_dest; + size_t m_remainder; +}; + +class BlockWriter +{ + public: + BlockWriter(const IOVec& ioVec); + + bool write(int socket); + bool done() const { return m_remainder == 0; } + size_t remainder() const { return m_remainder; } + + private: + IOVec m_source; + size_t m_remainder; +}; + +} // namespace STG + +#endif diff --git a/libs/common/include/stg/common.h b/libs/common/include/stg/common.h new file mode 100644 index 00000000..94cf9f06 --- /dev/null +++ b/libs/common/include/stg/common.h @@ -0,0 +1,320 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + */ + + /* + $Revision: 1.32 $ + $Date: 2010/11/08 10:11:19 $ + $Author: faust $ + */ + +#ifndef common_h +#define common_h + +//#include "stg/const.h" + +#include +#include +#include +#include // NAME_MAX +#include + +#include // uid_t, gid_t +#include // mode_t + +#define STAT_TIME_3 (1) +#define STAT_TIME_2 (2) +#define STAT_TIME_1 (3) +#define STAT_TIME_1_2 (4) +#define STAT_TIME_1_4 (5) +#define STAT_TIME_1_6 (6) + +#define FN_STR_LEN (NAME_MAX) + +#define ST_F 0 +#define ST_B 1 +#define ST_KB 2 +#define ST_MB 3 + +//----------------------------------------------------------------------------- +const char * IntToKMG(int64_t a, int statType = ST_F); +const char * LogDate(time_t t); +int ParesTimeStat(const char * str); +int IsTimeStat(struct tm * t, int statTime); +int strtodouble2(const char * str, double & value); +inline int strtodouble2(const std::string & str, double & value) { return strtodouble2(str.c_str(), value); } +int printfd(const char * __file__, const char * fmt, ...); +void Encode12(char * dst, const char * src, size_t srcLen); +void Decode21(char * dst, const char * src); + +void Encode12str(std::string & dst, const std::string & src); +void Decode21str(std::string & dst, const std::string & src); +inline std::string Encode12str(const std::string & src) { std::string dst; Encode12str(dst, src); return dst; } +inline std::string Decode21str(const std::string & src) { std::string dst; Decode21str(dst, src); return dst; } + +int ParseIPString(const char * str, uint32_t * ips, int maxIP); +void KOIToWin(const char * s1, char * s2, int l); +void WinToKOI(const char * s1, char * s2, int l); +void KOIToWin(const std::string & s1, std::string * s2); +void WinToKOI(const std::string & s1, std::string * s2); +int DaysInMonth(unsigned year, unsigned mon); +int DaysInCurrentMonth(); +int Min8(int a); +std::string inet_ntostring(uint32_t); +uint32_t inet_strington(const std::string & value); +std::string TimeToString(time_t time); +int strprintf(std::string * str, const char * fmt, ...); +int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2); +uint32_t CalcMask(uint32_t msk); +void TouchFile(const std::string & fileName); +#ifdef WIN32 +void EncodeStr(char * str, unsigned long serial, int useHDD); +void DecodeStr(char * str, unsigned long serial, int useHDD); +#endif //WIN32 +void SwapBytes(uint16_t & value); +void SwapBytes(uint32_t & value); +void SwapBytes(uint64_t & value); +void SwapBytes(int16_t & value); +void SwapBytes(int32_t & value); +void SwapBytes(int64_t & value); + +std::string & TrimL(std::string & val); +std::string & TrimR(std::string & val); +std::string & Trim(std::string & val); +std::string Trim(const std::string & val); + +std::string ToLower(std::string value); +std::string ToUpper(std::string value); + +template +inline +C Split(const std::string & value, char delim, F conv) +{ +C res; +size_t startPos = 0; +size_t pos = value.find_first_of(delim); +while (pos != std::string::npos) + { + res.push_back(conv(value.substr(startPos, pos - startPos))); + startPos = pos + 1; + pos = value.find_first_of(delim, pos + 1); + } +res.push_back(conv(value.substr(startPos, pos - startPos))); +return res; +} + +template +inline +T FromString(const std::string & value) +{ +T res; +std::istringstream stream(value); +stream >> res; +return res; +} + +template <> +inline +std::string FromString(const std::string & value) +{ +return value; +} + +template +inline +C Split(const std::string & value, char delim) +{ + return Split(value, delim, FromString); +} + +std::string IconvString(const std::string & source, const std::string & from, const std::string & to); + +int ParseInt(const std::string & str, int * val); +int ParseUnsigned(const std::string & str, unsigned * val); +int ParseIntInRange(const std::string & str, int min, int max, int * val); +int ParseUnsignedInRange(const std::string & str, unsigned min, + unsigned max, unsigned * val); +int ParseYesNo(const std::string & str, bool * val); + +bool WaitPackets(int sd); + +bool ReadAll(int sd, void * dest, size_t size); +bool WriteAll(int sd, const void * source, size_t size); + +std::string ToPrintable(const std::string & src); + +std::string formatTime(time_t value); +time_t readTime(const std::string & value); +//----------------------------------------------------------------------------- +int str2x(const std::string & str, int32_t & x); +int str2x(const std::string & str, uint32_t & x); +inline +int str2x(const std::string & str, double & x) { return strtodouble2(str.c_str(), x); } +#ifndef WIN32 +int str2x(const std::string & str, int64_t & x); +int str2x(const std::string & str, uint64_t & x); +#endif +//----------------------------------------------------------------------------- +const std::string & x2str(uint32_t x, std::string & s); +const std::string & x2str(uint64_t x, std::string & s); +//----------------------------------------------------------------------------- +const std::string & x2str(double x, std::string & s); +//----------------------------------------------------------------------------- + +template +int str2x(const std::string & str, varT & x); +template +const std::string & x2str(varT x, std::string & s); +template +std::string x2str(varT x) { std::string s; return x2str(x, s); } +template +const std::string & unsigned2str(varT x, std::string & s); +template +std::string unsigned2str(varT x) { std::string s; return unsigned2str(x, s); } + +//----------------------------------------------------------------------------- +template +inline +int str2x(const std::string & str, varT & x) +{ + int pos = 0; + int minus = 1; + + if (str.empty()) + return -1; + + if (str[0] == '+') + pos++; + + if (str[0] == '-') + { + pos++; + minus = -1; + } + + if ((str[pos] < '0' || str[pos] > '9')) + return -1; + + x = str[pos++] - '0'; + + for (unsigned i = pos; i < str.size(); i++) + { + if ((str[i] < '0' || str[i] > '9')) + return -1; + + x *= 10; + x += str[i] - '0'; + } + + x *= minus; + + return 0; +} +//----------------------------------------------------------------------------- +template +inline +const std::string & x2str(varT x, std::string & s) +{ + varT xx = x; + int pos = 1; + + x /= 10; + while (x != 0) + { + x /= 10; + pos++; + } + + if (xx < 0) + { + pos++; + s.resize(pos, 0); + s[0] = '-'; + } + else if (xx > 0) + { + s.resize(pos, 0); + } + else + { + s.resize(1, 0); + s[0] = '0'; + return s; + } + + x = xx; + + while (x != 0) + { + if (x < 0) + s[--pos] = -(x % 10) + '0'; + else + s[--pos] = x % 10 + '0'; + + x /= 10; + } + + return s; +} +//----------------------------------------------------------------------------- +template +inline +const std::string & unsigned2str(varT x, std::string & s) +{ + varT xx = x; + int pos = 1; + + x /= 10; + while (x != 0) + { + x /= 10; + pos++; + } + + if (xx > 0) + { + s.resize(pos, 0); + } + else + { + s.resize(1, 0); + s[0] = '0'; + return s; + } + + x = xx; + + while (x != 0) + { + s[--pos] = x % 10 + '0'; + + x /= 10; + } + + return s; +} +//----------------------------------------------------------------------------- +char * stg_strptime(const char *, const char *, struct tm *); +time_t stg_timegm(struct tm *); + +uid_t str2uid(const std::string& name); +gid_t str2gid(const std::string& name); +mode_t str2mode(const std::string& mode); + +#endif diff --git a/libs/common/strptime.cpp b/libs/common/strptime.cpp new file mode 100644 index 00000000..38b86b47 --- /dev/null +++ b/libs/common/strptime.cpp @@ -0,0 +1,19 @@ +/* + * $Revision: 1.1 $ + * $Date: 2007/05/17 08:25:58 $ + * + * This file contain a replacement of commonly used function strptime + * Under some OS's it appears only with _XOPEN_SOURCE definition + * + */ + +#define _XOPEN_SOURCE +#include + +#include "stg/common.h" + +char * stg_strptime(const char * a, const char * b, struct tm * tm) +{ +return strptime(a, b, tm); +} + diff --git a/libs/conffiles/CMakeLists.txt b/libs/conffiles/CMakeLists.txt new file mode 100644 index 00000000..34e18014 --- /dev/null +++ b/libs/conffiles/CMakeLists.txt @@ -0,0 +1,5 @@ +set ( CPP_FILES conffiles.cpp ) + +add_library ( conffiles STATIC ${CPP_FILES} ) + +target_include_directories ( conffiles PUBLIC include ) diff --git a/libs/conffiles/Makefile b/libs/conffiles/Makefile new file mode 100644 index 00000000..4d485578 --- /dev/null +++ b/libs/conffiles/Makefile @@ -0,0 +1,11 @@ +############################################################################### +# $Id: Makefile,v 1.4 2007/05/08 14:29:19 faust Exp $ +############################################################################### + +LIB_NAME = stgconffiles + +SRCS = conffiles.cpp + +INCS = conffiles.h + +include ../Makefile.in diff --git a/libs/conffiles/conffiles.cpp b/libs/conffiles/conffiles.cpp new file mode 100644 index 00000000..b254128b --- /dev/null +++ b/libs/conffiles/conffiles.cpp @@ -0,0 +1,423 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Date: 27.10.2002 + */ + +/* + * Author : Boris Mikhailenko + */ + + /* + $Revision: 1.5 $ + $Date: 2009/10/22 11:40:22 $ + */ + +//--------------------------------------------------------------------------- + +// getpid +#include +#include + +#include // E* +#include +#include +#include +#include + +#include + +#include "stg/conffiles.h" + +namespace +{ +//--------------------------------------------------------------------------- +std::string TrimL(std::string val) +{ +size_t pos = val.find_first_not_of(" \t"); +if (pos == std::string::npos) + { + val.erase(val.begin(), val.end()); + } +else + { + val.erase(0, pos); + } +return val; +} +//--------------------------------------------------------------------------- +std::string TrimR(std::string val) +{ +size_t pos = val.find_last_not_of(" \t"); +if (pos != std::string::npos) + { + val.erase(pos + 1); + } +return val; +} +//--------------------------------------------------------------------------- +std::string Trim(const std::string& val) +{ +return TrimR(TrimL(val)); +} +//--------------------------------------------------------------------------- +} // namespace anonymous + +//--------------------------------------------------------------------------- +bool StringCaseCmp(const std::string & str1, const std::string & str2) +{ +return (strcasecmp(str1.c_str(), str2.c_str()) < 0); +} +//--------------------------------------------------------------------------- +CONFIGFILE::CONFIGFILE(const std::string & fn, bool nook) + : param_val(StringCaseCmp), + fileName(fn), + error(0), + changed(false) +{ +std::ifstream f(fileName.c_str()); + +if (!f) + { + if (!nook) + error = -1; + return; + } + +std::string line; +while (getline(f, line)) + { + size_t pos = line.find('#'); + if (pos != std::string::npos) + line.resize(pos); + + if (line.find_first_not_of(" \t\r") == std::string::npos) + continue; + + pos = line.find_first_of('='); + if (pos == std::string::npos) + { + error = -1; + return; + } + + std::string parameter = Trim(line.substr(0, pos)); + std::string value = Trim(line.substr(pos + 1)); + param_val[parameter] = value; + } +} +//--------------------------------------------------------------------------- +CONFIGFILE::~CONFIGFILE() +{ +Flush(); +} +//--------------------------------------------------------------------------- +const std::string & CONFIGFILE::GetFileName() const +{ +return fileName; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::Error() const +{ +int e = error; +error = 0; +return e; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadString(const std::string & param, std::string * val, const std::string & defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + *val = it->second; + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +void CONFIGFILE::WriteString(const std::string & param, const std::string &val) +{ +param_val[param] = val; +changed = true; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadTime(const std::string & param, time_t * val, time_t defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = strtol(it->second.c_str(), &res, 10); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadInt(const std::string & param, int * val, int defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = static_cast(strtol(it->second.c_str(), &res, 10)); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadUInt(const std::string & param, unsigned int * val, unsigned int defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = static_cast(strtoul(it->second.c_str(), &res, 10)); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadLongInt(const std::string & param, long int * val, long int defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = strtol(it->second.c_str(), &res, 10); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadULongInt(const std::string & param, unsigned long int * val, unsigned long int defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = strtoul(it->second.c_str(), &res, 10); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadLongLongInt(const std::string & param, int64_t * val, int64_t defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = strtoll(it->second.c_str(), &res, 10); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadULongLongInt(const std::string & param, uint64_t * val, uint64_t defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = strtoull(it->second.c_str(), &res, 10); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadShortInt(const std::string & param, short int * val, short int defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = static_cast(strtol(it->second.c_str(), &res, 10)); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::ReadUShortInt(const std::string & param, unsigned short int * val, unsigned short int defaultVal) const +{ +const std::map::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = static_cast(strtoul(it->second.c_str(), &res, 10)); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +void CONFIGFILE::WriteInt(const std::string & param, int64_t val) +{ +char buf[32]; +snprintf(buf, sizeof(buf), "%lld", static_cast(val)); +param_val[param] = buf; +changed = true; +} +//--------------------------------------------------------------------------- +void CONFIGFILE::WriteTime(const std::string & param, time_t val) +{ +std::stringstream ss; +ss<::const_iterator it(param_val.find(param)); + +if (it != param_val.end()) + { + char *res; + *val = strtod(it->second.c_str(), &res); + if (*res != 0) + { + *val = defaultVal; //Error! + return EINVAL; + } + return 0; + } + +*val = defaultVal; +return -1; +} +//--------------------------------------------------------------------------- +void CONFIGFILE::WriteDouble(const std::string & param, double val) +{ +char s[30]; +snprintf(s, 30, "%f", val); +param_val[param] = s; +changed = true; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::Flush(const std::string & path) const +{ +std::ofstream f(path.c_str()); +if (!f.is_open()) + { + error = EIO; + return EIO; + } + +std::map::const_iterator it = param_val.begin(); +while (it != param_val.end()) + { + f << it->first << "=" << it->second << "\n"; + ++it; + } + +f.close(); +return 0; +} +//--------------------------------------------------------------------------- +int CONFIGFILE::Flush() const +{ +if (!changed) + return 0; + +char pid[6]; +snprintf(pid, sizeof(pid), "%d", getpid()); + +if (Flush(fileName + "." + pid)) + return -1; + +if (rename((fileName + "." + pid).c_str(), fileName.c_str())) + return -1; + +changed = false; + +return 0; +} +//--------------------------------------------------------------------------- diff --git a/libs/conffiles/include/stg/conffiles.h b/libs/conffiles/include/stg/conffiles.h new file mode 100644 index 00000000..710cd042 --- /dev/null +++ b/libs/conffiles/include/stg/conffiles.h @@ -0,0 +1,83 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Date: 27.10.2002 + */ + +/* + * Author : Boris Mikhailenko + */ + +/* + $Revision: 1.5 $ + $Date: 2009/06/22 16:00:38 $ + */ + +//--------------------------------------------------------------------------- + +#ifndef ConfFilesH +#define ConfFilesH + +#include +#include +#include + +//--------------------------------------------------------------------------- + +typedef bool (*StringCaseCmp_t)(const std::string & str1, const std::string & str2); + +class CONFIGFILE +{ +public: + CONFIGFILE(const std::string & fn, bool nook = false); + ~CONFIGFILE(); + const std::string & GetFileName() const; + + // æÕÎËÃÉÉ Read* ×ÏÚ×ÒÁÝÁÀÔ 0 ÐÒÉ ÕÓÐÅÛÎÏÍ ÓÞÉÔÙ×ÁÎÉÉ + // É EINVAL ÐÒÉ ÏÔÓÕÔÓ×ÉÉ ÐÁÒÁÍÅÔÒÁ É ×ÙÓÔÁ×ÌÑÀÔ defaulValue + //int ReadString(const std::string & param, char * val, int * maxLen, const char * defaultVal) const; + int ReadString(const std::string & param, std::string * val, const std::string & defaultVal) const; + int ReadTime(const std::string & param, time_t *, time_t) const; + int ReadShortInt(const std::string & param, short int *, short int) const; + int ReadInt(const std::string & param, int *, int) const; + int ReadLongInt(const std::string & param, long int *, long int) const; + int ReadLongLongInt(const std::string & param, int64_t *, int64_t) const; + int ReadUShortInt(const std::string & param, unsigned short int *, unsigned short int) const; + int ReadUInt(const std::string & param, unsigned int *, unsigned int) const; + int ReadULongInt(const std::string & param, unsigned long int *, unsigned long int) const; + int ReadULongLongInt(const std::string & param, uint64_t *, uint64_t) const; + int ReadDouble(const std::string & param, double * val, double defaultVal) const; + + void WriteString(const std::string & param, const char * val) { return WriteString(param, std::string(val)); } + void WriteString(const std::string & param, const std::string& val); + void WriteInt(const std::string & param, int64_t val); + void WriteDouble(const std::string & param, double val); + void WriteTime(const std::string & param, time_t val); + + int Error() const; + int Flush() const; + +private: + std::map param_val; + std::string fileName; + mutable int error; + mutable bool changed; + + int Flush(const std::string & path) const; +}; +//--------------------------------------------------------------------------- +#endif diff --git a/libs/crypto/CMakeLists.txt b/libs/crypto/CMakeLists.txt new file mode 100644 index 00000000..9b40d18b --- /dev/null +++ b/libs/crypto/CMakeLists.txt @@ -0,0 +1,6 @@ +set ( CPP_FILES bfstream.cpp ) +set ( C_FILES ag_md5.c blowfish.c ) + +add_library ( crypto STATIC ${CPP_FILES} ${C_FILES} ) + +target_include_directories ( crypto PUBLIC include ) diff --git a/libs/crypto/Makefile b/libs/crypto/Makefile new file mode 100644 index 00000000..47e91203 --- /dev/null +++ b/libs/crypto/Makefile @@ -0,0 +1,15 @@ +############################################################################### +# $Id: Makefile,v 1.5 2009/10/09 07:15:48 nobunaga Exp $ +############################################################################### + +LIB_NAME = stgcrypto + +SRCS = ag_md5.c \ + blowfish.c \ + bfstream.cpp + +INCS = ag_md5.h \ + blowfish.h \ + bfstream.h + +include ../Makefile.in diff --git a/libs/crypto/ag_md5.c b/libs/crypto/ag_md5.c new file mode 100644 index 00000000..a638c189 --- /dev/null +++ b/libs/crypto/ag_md5.c @@ -0,0 +1,455 @@ +#ifdef WIN32 +#include +#include +#else +#include +#include +#endif + +#include +#include +#include +#include + +#include "stg/ag_md5.h" + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +int i64c(int i) +{ + if (i <= 0) + return ('.'); + + if (i == 1) + return ('/'); + + if (i >= 2 && i < 12) + return ('0' - 2 + i); + + if (i >= 12 && i < 38) + return ('A' - 12 + i); + + if (i >= 38 && i < 63) + return ('a' - 38 + i); + + return ('z'); +} + +char * l64a_(long l) +{ + static char buf[8]; + int i = 0; + + if (l < 0L) + return ((char *) 0); + + do { + buf[i++] = i64c ((int) (l % 64)); + buf[i] = '\0'; + } while (l /= 64L, l > 0 && i < 6); + + return (buf); +} + +char * crypt_make_salt(void) +{ + + static char result[40]; + #ifdef WIN32 + unsigned int tsec; + #else + struct timeval tv; + #endif + + result[0] = '\0'; + strcpy(result, "$1$"); /* magic for the new MD5 crypt() */ + + /* + * Generate 8 chars of salt, the old crypt() will use only first 2. + */ + #ifdef WIN32 + strcat(result, l64a_(GetTickCount())); + tsec = time(NULL); + strcat(result, l64a_(tsec + getpid() + clock())); + #else + gettimeofday(&tv, (struct timezone *) 0); + strcat(result, l64a_(tv.tv_usec)); + strcat(result, l64a_(tv.tv_sec + getpid() + clock())); + #endif + + if (strlen(result) > 3 + 8) /* magic+salt */ + result[11] = '\0'; + + return result; +} + +void byteReverse(unsigned char *buf, unsigned longs) +{ + uint32_t t; + do { + t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(uint32_t *) buf = t; + buf += 4; + } while (--longs); +} + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, char const *buf, unsigned len) +{ + uint32_t t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void +MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + + /* Now fill the next block with 56 bytes */ + memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((uint32_t *) ctx->in)[14] = ctx->bits[0]; + ((uint32_t *) ctx->in)[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (uint32_t *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + memcpy(digest, ctx->buf, 16); + memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */ +} + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +void +MD5Transform(uint32_t buf[4], uint32_t const in[16]) +{ + register uint32_t a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void +to64(char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char * +libshadow_md5_crypt(const char *pw, const char *salt) +{ + static const char *magic = "$1$"; /* + * This string is magic for + * this algorithm. Having + * it this way, we can get + * get better later on + */ + static char passwd[120], *p; + static const char *sp,*ep; + unsigned char final[16]; + int sl,pl,i,j; + MD5_CTX ctx,ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if(!strncmp(sp,magic,strlen(magic))) + sp += strlen(magic); + + /* It stops at the first '$', max 8 chars */ + for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + MD5Init(&ctx); + + /* The password first, since that is what is most unknown */ + MD5Update(&ctx, pw, strlen(pw)); + + /* Then our magic string */ + MD5Update(&ctx, magic, strlen(magic)); + + /* Then the raw salt */ + MD5Update(&ctx, sp, sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + MD5Init(&ctx1); + MD5Update(&ctx1,pw,strlen(pw)); + MD5Update(&ctx1,sp,sl); + MD5Update(&ctx1,pw,strlen(pw)); + MD5Final(final,&ctx1); + for(pl = strlen(pw); pl > 0; pl -= 16) + MD5Update(&ctx, (char*)final, pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (j=0,i = strlen(pw); i ; i >>= 1) + if(i&1) + MD5Update(&ctx, (char*)final+j, 1); + else + MD5Update(&ctx, pw+j, 1); + + /* Now make the output string */ + strcpy(passwd,magic); + strncat(passwd,sp,sl); + strcat(passwd,"$"); + + MD5Final(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + /* + for(i=0;i<1000;i++) { + MD5Init(&ctx1); + if(i & 1) + MD5Update(&ctx1,pw,strlen(pw)); + else + MD5Update(&ctx1,final,16); + + if(i % 3) + MD5Update(&ctx1,sp,sl); + + if(i % 7) + MD5Update(&ctx1,pw,strlen(pw)); + + if(i & 1) + MD5Update(&ctx1,final,16); + else + MD5Update(&ctx1,pw,strlen(pw)); + MD5Final(final,&ctx1); + }*/ + + p = passwd + strlen(passwd); + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4; + l = final[11] ; to64(p,l,2); p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; +} + +char *pw_encrypt(const char *clear, const char *salt) { + + /* + * If the salt string from the password file or from crypt_make_salt() + * begins with the magic string, use the new algorithm. + */ + if (strncmp(salt, "$1$", 3) == 0) + return(libshadow_md5_crypt(clear, salt)); + else return(NULL); + +} +/* AG MD5 functions */ +char *make_ag_hash(time_t salt, const char *clear) { + char salt_str[20]; + char *res=NULL; + char *p; + + unsigned long slt = salt; + sprintf(salt_str, "$1$%08lx", slt); + res=libshadow_md5_crypt(clear, salt_str); + p=strrchr(res, '$'); + return(++p); +} + +int check_ag_hash(time_t salt, const char *clear, const char *hash) { + return(strcmp(hash, make_ag_hash(salt, clear))); +} + diff --git a/libs/crypto/bfstream.cpp b/libs/crypto/bfstream.cpp new file mode 100644 index 00000000..3325bd1a --- /dev/null +++ b/libs/crypto/bfstream.cpp @@ -0,0 +1,142 @@ +#include "stg/bfstream.h" + +#include "stg/blowfish.h" + +#include + +namespace +{ + +#ifndef BFSTREAM_BUF_SIZE +const size_t BUFFER_SIZE = 1024; +#else +const size_t BUFFER_SIZE = BFSTREAM_BUF_SIZE; +#endif + +class COMMON +{ + public: + typedef bool (* CALLBACK)(const void * block, size_t size, void * data); + typedef void (* PROC)(void * dest, const void * source, size_t length, const BLOWFISH_CTX * ctx); + + COMMON(const std::string & key, CALLBACK callback, void * data, PROC proc) + : m_ptr(m_buffer), + m_callback(callback), + m_data(data), + m_proc(proc), + m_ok(true) + { + InitContext(key.c_str(), key.length(), &m_ctx); + memset(m_buffer, 0, sizeof(m_buffer)); + } + + void Put(const void * data, size_t size, bool last) + { + size_t dataSize = m_ptr - m_buffer; + while (dataSize + size > sizeof(m_buffer)) + { + memcpy(m_ptr, data, sizeof(m_buffer) - dataSize); // Fill buffer + size -= sizeof(m_buffer) - dataSize; // Adjust size + data = static_cast(data) + sizeof(m_buffer) - dataSize; // Adjust data pointer + m_proc(m_buffer, m_buffer, sizeof(m_buffer), &m_ctx); // Process + m_ok = m_ok && m_callback(m_buffer, sizeof(m_buffer), m_data); // Consume + m_ptr = m_buffer; + dataSize = 0; + } + if (!m_ok) + return; + memcpy(m_ptr, data, size); + m_ptr += size; + m_tryConsume(last); + } + + bool IsOk() const { return m_ok; } + + private: + char m_buffer[BUFFER_SIZE]; + char * m_ptr; + CALLBACK m_callback; + void * m_data; + BLOWFISH_CTX m_ctx; + PROC m_proc; + bool m_ok; + + void m_tryConsume(bool last) + { + size_t dataSize = (m_ptr - m_buffer) & ~7; + size_t remainder = m_ptr - m_buffer - dataSize; + if (last && remainder > 0) + { + dataSize += 8; + remainder = 0; + } + if (!last && dataSize == 0) // Allow to call callback with 0 data on last call. + return; + m_proc(m_buffer, m_buffer, dataSize, &m_ctx); + m_ok = m_ok && m_callback(m_buffer, dataSize, m_data); + if (!m_ok) + return; + if (remainder > 0) + memmove(m_buffer, m_buffer + dataSize, remainder); + m_ptr = m_buffer + remainder; + } +}; + +} // namespace anonymous + +using STG::ENCRYPT_STREAM; +using STG::DECRYPT_STREAM; + +class ENCRYPT_STREAM::IMPL : public COMMON +{ + public: + IMPL(const std::string & key, CALLBACK callback, void * data) + : COMMON(key, callback, data, EncryptString) + {} +}; + +class DECRYPT_STREAM::IMPL : public COMMON +{ + public: + IMPL(const std::string & key, CALLBACK callback, void * data) + : COMMON(key, callback, data, DecryptString) + {} +}; + +ENCRYPT_STREAM::ENCRYPT_STREAM(const std::string & key, CALLBACK callback, void * data) + : m_impl(new IMPL(key, callback, data)) +{} + +ENCRYPT_STREAM::~ENCRYPT_STREAM() +{ +delete m_impl; +} + +void ENCRYPT_STREAM::Put(const void * data, size_t size, bool last) +{ +m_impl->Put(data, size, last); +} + +bool ENCRYPT_STREAM::IsOk() const +{ +return m_impl->IsOk(); +} + +DECRYPT_STREAM::DECRYPT_STREAM(const std::string & key, CALLBACK callback, void * data) + : m_impl(new IMPL(key, callback, data)) +{} + +DECRYPT_STREAM::~DECRYPT_STREAM() +{ +delete m_impl; +} + +void DECRYPT_STREAM::Put(const void * data, size_t size, bool last) +{ +m_impl->Put(data, size, last); +} + +bool DECRYPT_STREAM::IsOk() const +{ +return m_impl->IsOk(); +} diff --git a/libs/crypto/blowfish.c b/libs/crypto/blowfish.c new file mode 100644 index 00000000..384d3a10 --- /dev/null +++ b/libs/crypto/blowfish.c @@ -0,0 +1,528 @@ +/* + * Author : Paul Kocher + * E-mail : pck@netcom.com + * Date : 1997 + * Description: C implementation of the Blowfish algorithm. + */ + +#include + +#include "stg/const.h" +#include "stg/blowfish.h" + +#define ENCRYPT 0 +#define DECRYPT 1 + +#define endianBig ((unsigned char) 0x45) +#define endianLittle ((unsigned char) 0x54) + +#define MIN(a,b) ((a) < (b) ? a : b) + +#ifdef WIN32 /* Win32 doesn't have random() or lstat */ + #define random() rand() + #define initstate(x,y,z) srand(x) + #define lstat(x,y) stat(x,y) +#endif + +#ifndef S_ISREG + #define S_ISREG(x) ( ((x)&S_IFMT)==S_IFREG ) +#endif + + +#define N 16 + +static uint32_t F(const BLOWFISH_CTX *ctx, uint32_t x); +static const uint32_t ORIG_P[16 + 2] = { +0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, +0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, +0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, +0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, +0x9216D5D9L, 0x8979FB1BL +}; + +static const uint32_t ORIG_S[4][256] = { +{ 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL}, + +{ 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L}, + +{ 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L}, + +{ 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L} +}; +//----------------------------------------------------------------------------- +uint32_t F(const BLOWFISH_CTX *ctx, uint32_t x) +{ +unsigned short a, b, c, d; +uint32_t y = 0; +//uint32_t y1, y2; + +d = x & 0x00FF; +x >>= 8; +c = x & 0x00FF; +x >>= 8; +b = x & 0x00FF; +x >>= 8; +a = x & 0x00FF; + +/*y1 = ctx->S[0][a]; +y2 = ctx->S[1][b]; +y = y1+y2;*/ + +y = ctx->S[0][a] + ctx->S[1][b]; +y = y ^ ctx->S[2][c]; +y = y + ctx->S[3][d]; +return y; +} +//----------------------------------------------------------------------------- +void Blowfish_Encrypt(const BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr) +{ +uint32_t Xl; +uint32_t Xr; +uint32_t temp; +short i; + +Xl = *xl; +Xr = *xr; + +for (i = 0; i < N; ++i) + { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + temp = Xl; + Xl = Xr; + Xr = temp; + } + +temp = Xl; +Xl = Xr; +Xr = temp; +Xr = Xr ^ ctx->P[N]; +Xl = Xl ^ ctx->P[N + 1]; +*xl = Xl; +*xr = Xr; +} +//----------------------------------------------------------------------------- +void Blowfish_Decrypt(const BLOWFISH_CTX *ctx, uint32_t *xl, uint32_t *xr) +{ +uint32_t Xl; +uint32_t Xr; +uint32_t temp; +short i; + +Xl = *xl; +Xr = *xr; + +for (i = N + 1; i > 1; --i) + { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + +/* Exchange Xl and Xr */ +temp = Xl; +Xl = Xr; +Xr = temp; +Xr = Xr ^ ctx->P[1]; +Xl = Xl ^ ctx->P[0]; +*xl = Xl; +*xr = Xr; +} +//----------------------------------------------------------------------------- +void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen) +{ +int i, j, k; +uint32_t data, datal, datar; + +memset(ctx->S, 0, sizeof(ctx->S)); + +for (i = 0; i < 4; i++) + { + + for (j = 0; j < 256; j++) + ctx->S[i][j] = ORIG_S[i][j]; + } + +j = 0; + +for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + + for (k = 0; k < 4; ++k) + { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keyLen) + j = 0; + } + + ctx->P[i] = ORIG_P[i] ^ data; + } + +datal = 0x00000000; +datar = 0x00000000; + +for (i = 0; i < N + 2; i += 2) + { + Blowfish_Encrypt(ctx, &datal, &datar); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + +for (i = 0; i < 4; ++i) + { + + for (j = 0; j < 256; j += 2) + { + Blowfish_Encrypt(ctx, &datal, &datar); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } +} +//----------------------------------------------------------------------------- +void InitContext(const char * passwd, size_t length, BLOWFISH_CTX * ctx) +{ +unsigned char keyL[PASSWD_LEN]; + +memset(keyL, 0, PASSWD_LEN); + +strncpy((char *)keyL, passwd, MIN(length, PASSWD_LEN)); + +Blowfish_Init(ctx, keyL, PASSWD_LEN); +} +//----------------------------------------------------------------------------- +// Note: swap bytes order for compatibility with OpenSSL +uint32_t bytes2block(const char * c) +{ + uint32_t t = (unsigned char)(*c++); + t += (unsigned char)(*c++) << 8; + t += (unsigned char)(*c++) << 16; + t += (unsigned char)(*c) << 24; + return t; +} +//----------------------------------------------------------------------------- +// Note: swap bytes order for compatibility with OpenSSL +void block2bytes(uint32_t t, char * c) +{ + *c++ = t & 0x000000FF; + *c++ = t >> 8 & 0x000000FF; + *c++ = t >> 16 & 0x000000FF; + *c = t >> 24 & 0x000000FF; +} +//----------------------------------------------------------------------------- +void DecryptBlock(void * d, const void * s, const BLOWFISH_CTX *ctx) +{ +const char * src = s; +char * dest = d; +uint32_t a = bytes2block(src); +uint32_t b = bytes2block(src + 4); + +Blowfish_Decrypt(ctx, &a, &b); + +block2bytes(a, dest); +block2bytes(b, dest + 4); +} +//----------------------------------------------------------------------------- +void EncryptBlock(void * d, const void * s, const BLOWFISH_CTX *ctx) +{ +const char * src = s; +char * dest = d; +uint32_t a = bytes2block(src); +uint32_t b = bytes2block(src + 4); + +Blowfish_Encrypt(ctx, &a, &b); + +block2bytes(a, dest); +block2bytes(b, dest + 4); +} +//----------------------------------------------------------------------------- +void DecryptString(void * d, const void * s, size_t length, const BLOWFISH_CTX * ctx) +{ +const char * src = s; +char * dest = d; +size_t pos = 0; +while (pos < length) + { + DecryptBlock(dest + pos, src + pos, ctx); + pos += 8; + } +} +//----------------------------------------------------------------------------- +void EncryptString(void * d, const void * s, size_t length, const BLOWFISH_CTX * ctx) +{ +const char * src = s; +char * dest = d; +size_t pos = 0; +while (pos < length) + { + if (pos + 8 < length) + EncryptBlock(dest + pos, src + pos, ctx); + else + { + // Short string, use 0-padded buffer. + char buf[8]; + memset(buf, 0, sizeof(buf)); + memcpy(buf, src + pos, length - pos); + EncryptBlock(dest + pos, buf, ctx); + } + pos += 8; + } +} +//----------------------------------------------------------------------------- diff --git a/libs/crypto/include/stg/ag_md5.h b/libs/crypto/include/stg/ag_md5.h new file mode 100644 index 00000000..e56b09e5 --- /dev/null +++ b/libs/crypto/include/stg/ag_md5.h @@ -0,0 +1,36 @@ +#ifndef _MD5_H +#define _MD5_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct MD5Context { + uint32_t buf[4]; + uint32_t bits[2]; + unsigned char in[64]; +}; + +typedef struct MD5Context MD5_CTX; + +char *crypt_make_salt(void); +void byteReverse(unsigned char*, unsigned); +void MD5Init(struct MD5Context *ctx); +void MD5Update(struct MD5Context*, char const*, unsigned); +void MD5Final(unsigned char digest[16], struct MD5Context *ctx); +void MD5Transform(uint32_t buf[4], uint32_t const in[16]); +char *libshadow_md5_crypt(const char*, const char*); +char *pw_encrypt(const char*, const char*); + +/* AG functions */ +char *make_ag_hash(time_t salt, const char *clear); +int check_ag_hash(time_t salt, const char *clear, const char *hash); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/crypto/include/stg/bfstream.h b/libs/crypto/include/stg/bfstream.h new file mode 100644 index 00000000..ae955b94 --- /dev/null +++ b/libs/crypto/include/stg/bfstream.h @@ -0,0 +1,46 @@ +#ifndef __STG_STGLIBS_BF_STREAM_H__ +#define __STG_STGLIBS_BF_STREAM_H__ + +#include +#include // size_t + +namespace STG +{ + +class ENCRYPT_STREAM +{ + public: + typedef bool (* CALLBACK)(const void * block, size_t size, void * data); + + ENCRYPT_STREAM(const std::string & key, CALLBACK callback, void * data); + ~ENCRYPT_STREAM(); + void Put(const void * data, size_t size, bool last = false); + + bool IsOk() const; + + private: + class IMPL; + + IMPL * m_impl; +}; + +class DECRYPT_STREAM +{ + public: + typedef bool (* CALLBACK)(const void * block, size_t size, void * data); + + DECRYPT_STREAM(const std::string & key, CALLBACK callback, void * data); + ~DECRYPT_STREAM(); + void Put(const void * data, size_t size, bool last = false); + + bool IsOk() const; + + private: + class IMPL; + + IMPL * m_impl; +}; + +} // namespace STG + +#endif diff --git a/libs/crypto/include/stg/blowfish.h b/libs/crypto/include/stg/blowfish.h new file mode 100644 index 00000000..6a4e6f31 --- /dev/null +++ b/libs/crypto/include/stg/blowfish.h @@ -0,0 +1,43 @@ +/* + * Author : Paul Kocher + * E-mail : pck@netcom.com + * Date : 1997 + * Description: C implementation of the Blowfish algorithm. + */ + +#ifndef BLOWFISH_H +#define BLOWFISH_H + +#define MAXKEYBYTES 56 /* 448 bits */ + +#ifdef __cplusplus +#include // size_t +#include +extern "C" { +#else +#include // size_t +#include +#endif + +typedef struct { + uint32_t P[16 + 2]; + uint32_t S[4][256]; +} BLOWFISH_CTX; + +void Blowfish_Init(BLOWFISH_CTX * ctx, unsigned char * key, int keyLen); +void Blowfish_Encrypt(const BLOWFISH_CTX * ctx, uint32_t * xl, uint32_t * xr); +void Blowfish_Decrypt(const BLOWFISH_CTX * ctx, uint32_t * xl, uint32_t * xr); + +void InitContext(const char * key, size_t length, BLOWFISH_CTX * ctx); +void DecryptBlock(void * d, const void * s, const BLOWFISH_CTX * ctx); +void EncryptBlock(void * d, const void * s, const BLOWFISH_CTX * ctx); + +void DecryptString(void * d, const void * s, size_t length, const BLOWFISH_CTX * ctx); +void EncryptString(void * d, const void * s, size_t length, const BLOWFISH_CTX * ctx); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/libs/dotconfpp/CMakeLists.txt b/libs/dotconfpp/CMakeLists.txt new file mode 100644 index 00000000..eec079ed --- /dev/null +++ b/libs/dotconfpp/CMakeLists.txt @@ -0,0 +1,5 @@ +set ( CPP_FILES dotconfpp.cpp mempool.cpp ) + +add_library ( dotconfpp STATIC ${CPP_FILES} ) + +target_include_directories ( dotconfpp PUBLIC include ) diff --git a/libs/dotconfpp/Makefile b/libs/dotconfpp/Makefile new file mode 100644 index 00000000..52c44833 --- /dev/null +++ b/libs/dotconfpp/Makefile @@ -0,0 +1,12 @@ +############################################################################### +# $Id: Makefile,v 1.3 2007/05/08 14:29:19 faust Exp $ +############################################################################### + +LIB_NAME = stgdotconfpp + +SRCS = dotconfpp.cpp \ + mempool.cpp + +INCS = dotconfpp.h + +include ../Makefile.in diff --git a/libs/dotconfpp/dotconfpp.cpp b/libs/dotconfpp/dotconfpp.cpp new file mode 100644 index 00000000..8f766f01 --- /dev/null +++ b/libs/dotconfpp/dotconfpp.cpp @@ -0,0 +1,664 @@ +/* Copyright (C) 2003 Aleksey Krivoshey +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include // dirname +#include // glob +#include + +#include "stg/dotconfpp.h" +#include "mempool.h" + +DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL), + values(NULL), valuesCount(0), + name(NULL), lineNum(0), fileName(NULL), closed(true) +{ +} + +DOTCONFDocumentNode::~DOTCONFDocumentNode() +{ + free(name); + if(values != NULL){ + for(int i = 0 ; i < valuesCount; i++){ + free(values[i]); + } + free(values); + } +} + +void DOTCONFDocumentNode::pushValue(char * _value) +{ + valuesCount++; + values = (char**)realloc(values, valuesCount*sizeof(char*)); + values[valuesCount-1] = strdup(_value); +} + +const char* DOTCONFDocumentNode::getValue(int index) const +{ + if(index >= valuesCount){ + return NULL; + } + return values[index]; +} + +DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity): + mempool(NULL), + curParent(NULL), curPrev(NULL), errorCallback(NULL), errorCallbackData(NULL), + curLine(0), file(NULL), fileName(NULL) +{ + if(caseSensitivity == CASESENSITIVE){ + cmp_func = strcmp; + } else { + cmp_func = strcasecmp; + } + + mempool = new AsyncDNSMemPool(1024); + mempool->initialize(); +} + +DOTCONFDocument::~DOTCONFDocument() +{ + for(std::list::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){ + delete(*i); + } + for(std::list::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){ + free(*i); + } + for(std::list::iterator i = processedFiles.begin(); i != processedFiles.end(); ++i){ + free(*i); + } + free(fileName); + delete mempool; +} + +int DOTCONFDocument::cleanupLine(char * line) +{ + char * start = line; + char * bg = line; + bool multiline = false; + bool concat = false; + char * word = NULL; + + if(!words.empty() && quoted) + concat = true; + + while(*line){ + if((*line == '#' || *line == ';') && !quoted){ + *bg = 0; + if(strlen(start)){ + //printf("2start='%s'\n", start); + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + break; + } + if(*line == '=' && !quoted){ // 'parameter = value' is the same as 'parameter value' but do not replace with ' ' when used in quoted value + *line = ' ';continue; + } + if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){ + *bg++ = *(line+1); + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'n'){ + *bg++ = '\n'; + line+=2; continue; + } + if(*line == '\\' && *(line+1) == 'r'){ + *bg++ = '\r'; + line+=2; continue; + } + if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){ //multiline + *bg = 0; + if(strlen(start)){ + //printf("3start='%s'\n", start); + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + multiline = true; + break; + } + if(*line == '"' || *line == '\''){ //need to handle quotes because of spaces or = that may be between + quoted = !quoted; + line++; continue; + } + if(isspace(*line) && !quoted){ + *bg++ = 0; + if(strlen(start)){ + //printf("start='%s'\n", start); + if(concat){ + word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1); + strcpy(word, words.back()); + strcat(word, start); + words.pop_back(); + concat = false; + } else { + word = mempool->strdup(start); + } + words.push_back(word); + } + start = bg; + while(isspace(*++line)) {}; + continue; + } + *bg++ = *line++; + } + + if(quoted && !multiline){ + error(curLine, fileName, "unterminated quote"); + return -1; + } + + return multiline?1:0; +} + +int DOTCONFDocument::parseLine() +{ + char * word = NULL; + char * nodeName = NULL; + char * nodeValue = NULL; + DOTCONFDocumentNode * tagNode = NULL; + bool newNode = false; + + for(std::list::iterator i = words.begin(); i != words.end(); ++i) { + word = *i; + + if(*word == '<'){ + newNode = true; + } + + if(newNode){ + nodeValue = NULL; + nodeName = NULL; + newNode = false; + } + + size_t wordLen = strlen(word); + if(word[wordLen-1] == '>'){ + word[wordLen-1] = 0; + newNode = true; + } + + if(nodeName == NULL){ + nodeName = word; + bool closed = true; //if this not <> node then it is closed by default + if(*nodeName == '<'){ + if(*(nodeName+1) != '/'){ //opening tag + nodeName++; + closed = false; + } else { //closing tag + nodeName+=2; + std::list::reverse_iterator i=nodeTree.rbegin(); + for(; i!=nodeTree.rend(); ++i){ + if(!cmp_func(nodeName, (*i)->name) && !(*i)->closed){ + (*i)->closed = true; + curParent = (*i)->parentNode; + curPrev = *i; + break; + } + } + if(i==nodeTree.rend()){ + error(curLine, fileName, "not matched closing tag ", nodeName); + return -1; + } + continue; + } + } + tagNode = new DOTCONFDocumentNode; + tagNode->name = strdup(nodeName); + tagNode->document = this; + tagNode->fileName = processedFiles.back(); + tagNode->lineNum = curLine; + tagNode->closed = closed; + if(!nodeTree.empty()){ + DOTCONFDocumentNode * prev = nodeTree.back(); + if(prev->closed){ + + curPrev->nextNode = tagNode; + tagNode->previousNode = curPrev; + tagNode->parentNode = curParent; + + } else { + prev->childNode = tagNode; + tagNode->parentNode = prev; + curParent = prev; + } + } + nodeTree.push_back(tagNode); + curPrev = tagNode; + } else { + nodeValue = word; + tagNode->pushValue(nodeValue); + } + } + + return 0; +} +int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent) +{ + char str[512]; + int ret = 0; + curLine = 0; + curParent = _parent; + + quoted = false; + + while(fgets(str, 511, file)){ + curLine++; + size_t slen = strlen(str); + if( slen >= 510 ){ + error(curLine, fileName, "warning: line too long"); + } + if(str[slen-1] != '\n'){ + str[slen] = '\n'; + str[slen+1] = 0; + } + if((ret = cleanupLine(str)) == -1){ + break; + } + if(ret == 0){ + if(!words.empty()){ + ret = parseLine(); + mempool->free(); + words.clear(); + if(ret == -1){ + break; + } + } + } + } + + return ret; +} + +int DOTCONFDocument::checkConfig(const std::list::iterator & from) +{ + int ret = 0; + + for(std::list::iterator i = from; i != nodeTree.end(); ++i){ + DOTCONFDocumentNode * tagNode = *i; + if(!tagNode->closed){ + error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name); + ret = -1; + break; + } + int vi = 0; + while( vi < tagNode->valuesCount ){ + //if((tagNode->values[vi])[0] == '$' && (tagNode->values[vi])[1] == '{' && strchr(tagNode->values[vi], '}') ){ + if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){ + ret = macroSubstitute(tagNode, vi ); + mempool->free(); + if(ret == -1){ + break; + } + } + vi++; + } + if(ret == -1){ + break; + } + } + + return ret; +} + +int DOTCONFDocument::setContent(const char * _fileName) +{ + int ret = 0; + char realpathBuf[PATH_MAX]; + + if(realpath(_fileName, realpathBuf) == NULL){ + error(0, _fileName, "%s", strerror(errno)); + return -1; + } + + fileName = strdup(realpathBuf); + + char * forPathName = strdup(realpathBuf); + + if (forPathName == NULL) { + error(0, NULL, "Not enought memory to duplicate realpath"); + return -1; + } + + char * _pathName = dirname(forPathName); + + std::string pathName(_pathName); + + free(forPathName); // From strdup + + processedFiles.push_back(strdup(realpathBuf)); + + if(( file = fopen(fileName, "r")) == NULL){ + error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno)); + return -1; + } + + ret = parseFile(); + + (void) fclose(file); + + if(!ret){ + + if( (ret = checkConfig(nodeTree.begin())) == -1){ + return -1; + } + + std::list::iterator from; + DOTCONFDocumentNode * tagNode = NULL; + int vi = 0; + for(std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ + tagNode = *i; + if(!cmp_func("IncludeFile", tagNode->name)){ + vi = 0; + while( vi < tagNode->valuesCount ){ + glob_t globBuf; + std::string nodeFilePath; + if (*tagNode->values[vi] != '/') { + // Relative path + nodeFilePath = pathName + "/" + tagNode->values[vi]; + } else { + // Absolute path + nodeFilePath = tagNode->values[vi]; + } + int res = glob(nodeFilePath.c_str(), 0, NULL, &globBuf); + if (res) { + switch (res) { + case GLOB_NOSPACE: + error(tagNode->lineNum, tagNode->fileName, "glob call failed for '%s': no free space", nodeFilePath.c_str()); + return -1; +#ifndef FREE_BSD + case GLOB_ABORTED: + // printf("Read error\n"); + // Ignore that error + break; + case GLOB_NOMATCH: + // printf("No match\n"); + // Ignore that error + break; +#endif + default: + error(tagNode->lineNum, tagNode->fileName, "glob call failed for '%s': unknown error", nodeFilePath.c_str()); + return -1; + } + } + if (!res) { + for (size_t i = 0; i < globBuf.gl_pathc; ++i) { + std::string nodeFilePath(globBuf.gl_pathv[i]); + if(access(nodeFilePath.c_str(), R_OK) == -1){ + error(tagNode->lineNum, tagNode->fileName, "%s: %s", nodeFilePath.c_str(), strerror(errno)); + continue; + } + if(realpath(nodeFilePath.c_str(), realpathBuf) == NULL){ + error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", nodeFilePath.c_str(), strerror(errno)); + continue; + } + + bool processed = false; + for(std::list::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode){ + if(!strcmp(*itInode, realpathBuf)){ + processed = true; + break; + } + } + if(processed){ + break; + } + + processedFiles.push_back(strdup(realpathBuf)); + + file = fopen(nodeFilePath.c_str(), "r"); + if(file == NULL){ + error(tagNode->lineNum, fileName, "failed to open file '%s': %s", nodeFilePath.c_str(), strerror(errno)); + continue; + } + //free(fileName); + fileName = strdup(realpathBuf); + from = nodeTree.end(); --from; + + if(tagNode->parentNode){ + DOTCONFDocumentNode * nd = tagNode->parentNode->childNode; + while(nd){ + if(!nd->nextNode) + break; + nd = nd->nextNode; + } + + curPrev = nd; + } + ret = parseFile(tagNode->parentNode); + + //ret = parseFile(tagNode->parentNode); + (void) fclose(file); + if(ret == -1) + continue; + if(checkConfig(++from) == -1){ + continue; + } + } + } + globfree(&globBuf); + vi++; + } + } + } + /* + if( (ret = checkConfig(nodeTree.begin())) == -1){ + return -1; + } + */ + + if(!requiredOptions.empty()) + ret = checkRequiredOptions(); + } + + return ret; +} + +int DOTCONFDocument::checkRequiredOptions() +{ + for(std::list::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){ + bool matched = false; + for(std::list::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){ + if(!cmp_func((*i)->name, *ci)){ + matched = true; + break; + } + } + if(!matched){ + error(0, NULL, "required option '%s' not specified", *ci); + return -1; + } + } + return 0; +} + +void DOTCONFDocument::error(int lineNum, const char * fileName, const char * fmt, ...) +{ + va_list args; + va_start(args, fmt); + + char msg[256]; + + vsnprintf(msg, 256, fmt, args); + + size_t len = (lineNum!=0?strlen(fileName):0) + strlen(msg) + 50; + char * buf = (char*)mempool->alloc(len); + + if(lineNum) + (void) snprintf(buf, len, "File '%s', line %d: %s\n", fileName, lineNum, msg); + else + (void) snprintf(buf, len, "File '%s': %s\n", fileName, msg); + + if (errorCallback) { + errorCallback(errorCallbackData, buf); + } else { + (void) vfprintf(stderr, buf, args); + } + + va_end(args); +} + +char * DOTCONFDocument::getSubstitution(char * macro, int lineNum) +{ + char * buf = NULL; + char * variable = macro+2; + + char * endBr = strchr(macro, '}'); + + if(!endBr){ + error(lineNum, fileName, "unterminated '{'"); + return NULL; + } + *endBr = 0; + + char * defaultValue = strchr(variable, ':'); + + if(defaultValue){ + *defaultValue++ = 0; + if(*defaultValue != '-'){ + error(lineNum, fileName, "incorrect macro substitution syntax"); + return NULL; + } + defaultValue++; + if(*defaultValue == '"' || *defaultValue == '\''){ + defaultValue++; + defaultValue[strlen(defaultValue)-1] = 0; + } + } else { + defaultValue = NULL; + } + + char * subs = getenv(variable); + if( subs ){ + buf = mempool->strdup(subs); + } else { + std::list::iterator i = nodeTree.begin(); + for(; i!=nodeTree.end(); ++i){ + DOTCONFDocumentNode * tagNode = *i; + if(!cmp_func(tagNode->name, variable)){ + if(tagNode->valuesCount != 0){ + buf = mempool->strdup(tagNode->values[0]); + break; + } + } + } + if( i == nodeTree.end() ){ + if( defaultValue ){ + buf = mempool->strdup(defaultValue); + } else { + error(lineNum, fileName, "substitution not found and default value not given"); + return NULL; + } + } + } + return buf; +} + +int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex) +{ + int ret = 0; + char * macro = tagNode->values[valueIndex]; + size_t valueLen = strlen(tagNode->values[valueIndex])+1; + char * value = (char*)mempool->alloc(valueLen); + char * v = value; + char * subs = NULL; + + while(*macro){ + if(*macro == '$' && *(macro+1) == '{'){ + char * m = strchr(macro, '}'); + subs = getSubstitution(macro, tagNode->lineNum); + if(subs == NULL){ + ret = -1; + break; + } + macro = m + 1; + *v = 0; + v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen); + strcpy(v, value); + value = strcat(v, subs); + v = value + strlen(value); + continue; + } + *v++ = *macro++; + } + *v = 0; + + free(tagNode->values[valueIndex]); + tagNode->values[valueIndex] = strdup(value); + return ret; +} + +const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const +{ + if ( !nodeTree.empty() ) { + return *nodeTree.begin(); + } else { + return NULL; + } +} + +const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const +{ + //printf("nodeName=%s, cont=%s, start=%s\n", nodeName, containingNode!=NULL?containingNode->name:"NULL", startNode!=NULL?startNode->name:"NULL"); + + std::list::const_iterator i = nodeTree.begin(); + + if(startNode == NULL) + startNode = parentNode; + + if(startNode != NULL){ + while( i != nodeTree.end() && (*i) != startNode ){ + ++i; + } + if( i != nodeTree.end() ) ++i; + } + + for(; i!=nodeTree.end(); ++i){ + //if(parentNode != NULL && (*i)->parentNode != parentNode){ + if((*i)->parentNode != parentNode){ + continue; + } + if(!cmp_func(nodeName, (*i)->name)){ + return *i; + } + } + return NULL; +} + +void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames) +{ + while(*requiredOptionNames){ + requiredOptions.push_back(strdup( *requiredOptionNames )); + requiredOptionNames++; + } +} + diff --git a/libs/dotconfpp/include/stg/dotconfpp.h b/libs/dotconfpp/include/stg/dotconfpp.h new file mode 100644 index 00000000..d9231348 --- /dev/null +++ b/libs/dotconfpp/include/stg/dotconfpp.h @@ -0,0 +1,120 @@ +/* Copyright (C) 2003 Aleksey Krivoshey +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef DOTCONFPP_H +#define DOTCONFPP_H + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +typedef void (* DOTCONFCallback) (void * data, const char * buf); + +class DOTCONFDocument; +class AsyncDNSMemPool; + +class DOTCONFDocumentNode +{ +friend class DOTCONFDocument; +private: + DOTCONFDocumentNode * previousNode; + DOTCONFDocumentNode * nextNode; + DOTCONFDocumentNode * parentNode; + DOTCONFDocumentNode * childNode; + char ** values; + int valuesCount; + char * name; + const DOTCONFDocument * document; + int lineNum; + char * fileName; + bool closed; + + void pushValue(char * _value); + +public: + DOTCONFDocumentNode(); + ~DOTCONFDocumentNode(); + + const char * getConfigurationFileName() const { return fileName; } + int getConfigurationLineNumber() const { return lineNum; } + + const DOTCONFDocumentNode * getNextNode() const { return nextNode; } + const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; } + const DOTCONFDocumentNode * getParentNode() const { return parentNode; } + const DOTCONFDocumentNode * getChildNode() const { return childNode; } + const char * getValue(int index = 0) const; + const char * getName() const { return name; } + const DOTCONFDocument * getDocument() const { return document; } +}; + +class DOTCONFDocument +{ +public: + enum CaseSensitive { CASESENSITIVE, CASEINSENSITIVE }; +protected: + AsyncDNSMemPool * mempool; +private: + DOTCONFDocumentNode * curParent; + DOTCONFDocumentNode * curPrev; + DOTCONFCallback errorCallback; + void * errorCallbackData; + int curLine; + bool quoted; + std::list nodeTree; + std::list requiredOptions; + std::list processedFiles; + FILE * file; + char * fileName; + std::list words; + int (* cmp_func)(const char *, const char *); + + int checkRequiredOptions(); + int parseLine(); + int parseFile(DOTCONFDocumentNode * _parent = NULL); + int checkConfig(const std::list::iterator & from); + int cleanupLine(char * line); + char * getSubstitution(char * macro, int lineNum); + int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex); + +protected: + virtual void error(int lineNum, const char * fileName, const char * fmt, ...); + +public: + explicit DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSITIVE); + virtual ~DOTCONFDocument(); + + void setErrorCallback(DOTCONFCallback _callback, void * _data) { errorCallback = _callback; errorCallbackData = _data; } + + int setContent(const char * _fileName); + + void setRequiredOptionNames(const char ** requiredOptionNames); // !TERMINATE ARRAY WITH NULL + const DOTCONFDocumentNode * getFirstNode() const; + const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const; +}; + +#endif diff --git a/libs/dotconfpp/mempool.cpp b/libs/dotconfpp/mempool.cpp new file mode 100644 index 00000000..3469418c --- /dev/null +++ b/libs/dotconfpp/mempool.cpp @@ -0,0 +1,116 @@ +/* Copyright (C) 2003 Aleksey Krivoshey +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#include "mempool.h" + +AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size): + pool(NULL), pos(0), size(_size) +{ + pool = ::malloc(size); +} + +AsyncDNSMemPool::PoolChunk::~PoolChunk() +{ + ::free(pool); +} + +AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize): + chunks(NULL), chunksCount(0), defaultSize(_defaultSize), + poolUsage(0), poolUsageCounter(0) +{ +} + +AsyncDNSMemPool::~AsyncDNSMemPool() +{ + for(size_t i = 0; isize - chunk->pos) >= size){ + chunk->pos += size; + return ((u_int8_t*)chunk->pool) + chunk->pos - size; + } + } + addNewChunk(size); + chunks[chunksCount-1]->pos = size; + return chunks[chunksCount-1]->pool; +} + +void AsyncDNSMemPool::free() +{ + size_t pu = 0; + size_t psz = 0; + poolUsageCounter++; + + for(size_t i = 0; ipos; + psz += chunks[i]->size; + chunks[i]->pos = 0; + } + poolUsage=(poolUsage>pu)?poolUsage:pu; + + if(poolUsageCounter >= 10 && chunksCount > 1){ + psz -= chunks[chunksCount-1]->size; + if(poolUsage < psz){ + chunksCount--; + delete chunks[chunksCount]; + } + poolUsage = 0; + poolUsageCounter = 0; + } +} + +void * AsyncDNSMemPool::calloc(size_t size) +{ + return ::memset(this->alloc(size), 0, size); +} + +char * AsyncDNSMemPool::strdup(const char *str) +{ + return ::strcpy((char*)this->alloc(strlen(str)+1), str); +} + diff --git a/libs/dotconfpp/mempool.h b/libs/dotconfpp/mempool.h new file mode 100644 index 00000000..9975611d --- /dev/null +++ b/libs/dotconfpp/mempool.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2003 Aleksey Krivoshey +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +#ifndef ASYNC_DNS_MEMPOOL_H +#define ASYNC_DNS_MEMPOOL_H + +#include +#include +#include + +class AsyncDNSMemPool +{ +private: + struct PoolChunk { + void * pool; + size_t pos; + size_t size; + + PoolChunk(size_t _size); + ~PoolChunk(); + }; + PoolChunk ** chunks; + size_t chunksCount; + size_t defaultSize; + + size_t poolUsage; + size_t poolUsageCounter; + + void addNewChunk(size_t size); + +public: + AsyncDNSMemPool(size_t _defaultSize = 4096); + virtual ~AsyncDNSMemPool(); + + int initialize(); + void free(); + void * alloc(size_t size); + void * calloc(size_t size); + char * strdup(const char *str); +}; + +#endif + diff --git a/libs/ia/CMakeLists.txt b/libs/ia/CMakeLists.txt new file mode 100644 index 00000000..73ab8e46 --- /dev/null +++ b/libs/ia/CMakeLists.txt @@ -0,0 +1,7 @@ +set ( CPP_FILES ia.cpp ) + +add_library ( ia STATIC ${CPP_FILES} ) + +target_include_directories ( ia PUBLIC include ) + +target_link_libraries ( ia crypto common ) diff --git a/libs/ia/Makefile b/libs/ia/Makefile new file mode 100644 index 00000000..3ab0306a --- /dev/null +++ b/libs/ia/Makefile @@ -0,0 +1,18 @@ +############################################################################### +# $Id: Makefile,v 1.11 2010/08/18 07:47:03 faust Exp $ +############################################################################### + +LIB_NAME = stgia + +SRCS = ia.cpp + +INCS = ia.h + +STGLIBS = -lstgcrypto + +LIBS = $(LIB_THREAD) + +LIB_INCS = -I ../crypto.lib/include \ + -I ../common.lib/include + +include ../Makefile.in diff --git a/libs/ia/ia.cpp b/libs/ia/ia.cpp new file mode 100644 index 00000000..a05d3061 --- /dev/null +++ b/libs/ia/ia.cpp @@ -0,0 +1,891 @@ +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 1, or (at your option) +** any later version. + +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. + +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + $Author: faust $ + $Revision: 1.15 $ + $Date: 2010/04/16 11:28:03 $ +*/ + +/* +* Author : +* Boris Mikhailenko +* Maxim Mamontov +* Andrey Rakhmanov - bugfixes. +*/ + +//--------------------------------------------------------------------------- + +#ifdef WIN32 +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include + +#include "stg/common.h" +#include "stg/ia.h" + +#define IA_NONE (0) +#define IA_CONNECT (1) +#define IA_DISCONNECT (2) + +#define IA_DEBUGPROTO 1 + +#define IA_ID "00100" +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +#ifndef WIN32 +#include +void Sleep(int ms) +{ +long long res = ms * 1000000; +struct timespec ts = {res / 1000000000, res % 1000000000}; +nanosleep(&ts, NULL); +} +//--------------------------------------------------------------------------- +void * RunL(void * data) +{ +sigset_t signalSet; +sigfillset(&signalSet); +pthread_sigmask(SIG_BLOCK, &signalSet, NULL); + +IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data; +static int a = 0; + +if (a == 0) + { + Sleep(50); + a = 1; + } + +while (c->GetNonstop()) + { + c->Run(); + } +return NULL; +} +//--------------------------------------------------------------------------- +long GetTickCount() +{ +struct timeval tv; +gettimeofday(&tv, NULL); +return tv.tv_sec*1000 + tv.tv_usec/1000; +} +#else +//--------------------------------------------------------------------------- +unsigned long WINAPI RunW(void * data) +{ +IA_CLIENT_PROT * c = (IA_CLIENT_PROT *)data; +while (c->GetNonstop()) + c->Run(); +return 0; +} +//--------------------------------------------------------------------------- +#endif + +namespace +{ + +bool HostNameToIP(const std::string & hostName, uint32_t & ip) +{ +ip = inet_addr(hostName.c_str()); +if (ip == INADDR_NONE) + { + hostent * phe = gethostbyname(hostName.c_str()); + if (phe) + { + ip = *((uint32_t *)phe->h_addr_list[0]); + } + else + { + return false; + } + } + +return true; +} + +} + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +IA_CLIENT_PROT::IA_CLIENT_PROT(const std::string & sn, unsigned short p, + const std::string & ln, uint16_t lp) + : action(IA_NONE), + phase(1), + phaseTime(0), + codeError(0), + nonstop(false), + isNetPrepared(false), + proxyMode(false), + serverName(sn), + port(p), + ip(0), + localName(ln), + localPort(lp), + firstConnect(true), + reconnect(0), + sockr(0), + protNum(0), + userTimeout(60), + aliveTimeout(5), + rnd(0), + pStatusChangedCb(NULL), + pStatChangedCb(NULL), + pInfoCb(NULL), + pErrorCb(NULL), + pDirNameCb(NULL), + statusChangedCbData(NULL), + statChangedCbData(NULL), + infoCbData(NULL), + errorCbData(NULL), + dirNameCbData(NULL), + connSyn8(NULL), + connSynAck8(NULL), + connAck8(NULL), + aliveSyn8(NULL), + aliveAck8(NULL), + disconnSyn8(NULL), + disconnSynAck8(NULL), + disconnAck8(NULL), + info(NULL) +{ +memset(&stat, 0, sizeof(stat)); + +#ifdef WIN32 +WSAStartup(MAKEWORD(2, 0), &wsaData); +#endif + +packetTypes["CONN_SYN"] = CONN_SYN_N; +packetTypes["CONN_SYN_ACK"] = CONN_SYN_ACK_N; +packetTypes["CONN_ACK"] = CONN_ACK_N; +packetTypes["ALIVE_SYN"] = ALIVE_SYN_N; +packetTypes["ALIVE_ACK"] = ALIVE_ACK_N; +packetTypes["DISCONN_SYN"] = DISCONN_SYN_N; +packetTypes["DISCONN_SYN_ACK"] = DISCONN_SYN_ACK_N; +packetTypes["DISCONN_ACK"] = DISCONN_ACK_N; +packetTypes["FIN"] = FIN_N; +packetTypes["ERR"] = ERROR_N; +packetTypes["INFO"] = INFO_N; +packetTypes["INFO_7"] = INFO_7_N; +packetTypes["INFO_8"] = INFO_8_N; + +unsigned char key[IA_PASSWD_LEN]; +memset(key, 0, IA_PASSWD_LEN); +strncpy((char *)key, "pr7Hhen", 8); +Blowfish_Init(&ctxHdr, key, IA_PASSWD_LEN); + +memset(key, 0, IA_PASSWD_LEN); +Blowfish_Init(&ctxPass, key, IA_PASSWD_LEN); + +for (size_t i = 0; i < DIR_NUM; ++i) + { + selectedDirs[i] = false; + } + +servAddr.sin_family = AF_INET; +servAddr.sin_port = htons(port); +servAddr.sin_addr.s_addr = ip; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::PrepareNet() +{ +/*struct hostent * phe; +unsigned long ip; + +ip = inet_addr(serverName.c_str()); +if (ip == INADDR_NONE) + { + phe = gethostbyname(serverName.c_str()); + if (phe) + { + ip = *((unsigned long*)phe->h_addr_list[0]); + } + else + { + strError = string("Unknown host ") + "\'" + serverName + "\'"; + codeError = IA_GETHOSTBYNAME_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData); + } + }*/ + +if (!HostNameToIP(serverName, ip)) + { + ip = 0; + strError = std::string("Unknown host ") + "\'" + serverName + "\'"; + codeError = IA_GETHOSTBYNAME_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData); + return; + } + +#ifndef WIN32 +close(sockr); +#else +closesocket(sockr); +#endif + +sockr = socket(AF_INET, SOCK_DGRAM, 0); + +struct sockaddr_in localAddrR; +localAddrR.sin_family = AF_INET; + +if (localPort) + localAddrR.sin_port = htons(localPort); +else + localAddrR.sin_port = htons(port); + +if (!localName.empty()) + { + if (!HostNameToIP(localName, localIP)) + { + strError = std::string("Unknown host ") + "\'" + serverName + "\'"; + codeError = IA_GETHOSTBYNAME_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_GETHOSTBYNAME_ERROR, errorCbData); + localIP = INADDR_ANY; + } + } +else + { + localIP = INADDR_ANY; + } + +localAddrR.sin_addr.s_addr = localIP; + +servAddr.sin_family = AF_INET; +servAddr.sin_port = htons(port); +servAddr.sin_addr.s_addr = ip; + +int res = bind(sockr, (struct sockaddr*)&localAddrR, sizeof(localAddrR)); +if (res == -1) + { + strError = "bind error"; + codeError = IA_BIND_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_BIND_ERROR, errorCbData); + return; + } + +#ifdef WIN32 +unsigned long arg = 1; +ioctlsocket(sockr, FIONBIO, &arg); +#else +if (0 != fcntl(sockr, F_SETFL, O_NONBLOCK)) + { + strError = "fcntl error"; + codeError = IA_FCNTL_ERROR; + if (pErrorCb != NULL) + pErrorCb(strError, IA_FCNTL_ERROR, errorCbData); + } +#endif + +} +//--------------------------------------------------------------------------- +IA_CLIENT_PROT::~IA_CLIENT_PROT() +{ +#ifndef WIN32 +close(sockr); +#else +closesocket(sockr); +WSACleanup(); +#endif +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::DeterminatePacketType(const char * buffer) +{ +std::map::iterator pi; +pi = packetTypes.find(buffer); +if (pi == packetTypes.end()) + { + return -1; + } +else + { + return pi->second; + } +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::FillHdr8(char * buffer, unsigned long) +{ +strncpy(buffer, IA_ID, 6); +buffer[IA_MAGIC_LEN] = 0; +buffer[IA_MAGIC_LEN + 1] = IA_PROTO_VER; +strncpy(buffer + sizeof(HDR_8), login.c_str(), IA_LOGIN_LEN); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Send(char * buffer, int len) +{ +if (!isNetPrepared) + { + PrepareNet(); + isNetPrepared = true; + } + +int db = sizeof(HDR_8); +EncryptString(buffer + db, buffer + db, IA_LOGIN_LEN, &ctxHdr); + +db += IA_LOGIN_LEN; +int encLen = (len - sizeof(HDR_8) - IA_LOGIN_LEN); +EncryptString(buffer + db, buffer + db, encLen, &ctxPass); + +return sendto(sockr, buffer, len, 0, (struct sockaddr*)&servAddr, sizeof(servAddr)); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Recv(char * buffer, int len) +{ +#ifdef WIN32 +int fromLen; +#else +socklen_t fromLen; +#endif + +struct sockaddr_in addr; +fromLen = sizeof(addr); +int res = recvfrom(sockr, buffer, len, 0, (struct sockaddr*)&addr, &fromLen); + +if (res == -1) + return res; + +if (strcmp(buffer + 4 + sizeof(HDR_8), "ERR")) + DecryptString(buffer, buffer, len, &ctxPass); + +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::NetSend(int n) +{ +char buffer[2048]; +int msgLen; + +memset(buffer, 0, 2048); + +switch (n) + { + case CONN_SYN_N: + msgLen = Prepare_CONN_SYN_8(buffer); + break; + + case CONN_ACK_N: + msgLen = Prepare_CONN_ACK_8(buffer); + break; + + case ALIVE_ACK_N: + msgLen = Prepare_ALIVE_ACK_8(buffer); + break; + + case DISCONN_SYN_N: + msgLen = Prepare_DISCONN_SYN_8(buffer); + break; + + case DISCONN_ACK_N: + msgLen = Prepare_DISCONN_ACK_8(buffer); + break; + + default: + return -1; + } + +FillHdr8(buffer, 0); +Send(buffer, msgLen); + +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::NetRecv() +{ +char buffer[2048]; + +if (Recv(buffer, sizeof(buffer)) < 0) + return -1; + +char packetName[20]; +strncpy(packetName, buffer + 12, sizeof(packetName)); +packetName[sizeof(packetName) - 1] = 0; +int pn = DeterminatePacketType(buffer + 12); + +int ret; +switch (pn) + { + case CONN_SYN_ACK_N: + ret = Process_CONN_SYN_ACK_8(buffer); + break; + + case ALIVE_SYN_N: + ret = Process_ALIVE_SYN_8(buffer); + break; + + case DISCONN_SYN_ACK_N: + ret = Process_DISCONN_SYN_ACK_8(buffer); + break; + + case FIN_N: + ret = Process_FIN_8(buffer); + break; + + case INFO_8_N: + ret = Process_INFO_8(buffer); + break; + + case ERROR_N: + ret = Process_ERROR(buffer); + break; + + default: + ret = -1; + } +return ret; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::Start() +{ +nonstop = true; +#ifdef WIN32 +unsigned long pt; +CreateThread(NULL, 16384, RunW, this, 0, &pt); +#else +pthread_create(&thread, NULL, RunL, this); +#endif +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::Stop() +{ +nonstop = false; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::Run() +{ +NetRecv(); + +switch (phase) + { + case 1: + if (action == IA_CONNECT) + { + action = IA_NONE; + NetSend(CONN_SYN_N); + phase = 2; + phaseTime = GetTickCount(); + } + if (reconnect && !firstConnect) + { + action = IA_CONNECT; + } + break; + + case 2: + if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout) + { + phase = 1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + } + + if (action == IA_DISCONNECT) + { + action = IA_NONE; + NetSend(DISCONN_SYN_N); + phase = 4; + phaseTime = GetTickCount(); + } + + break; + + case 3: + if ((int)(GetTickCount() - phaseTime)/1000 > userTimeout) + { + phase = 1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + firstConnect = false; + } + + if (action == IA_DISCONNECT) + { + action = IA_NONE; + NetSend(DISCONN_SYN_N); + phase = 4; + phaseTime = GetTickCount(); + } + + break; + + case 4: + if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout) + { + phase=1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + } + + if (action == IA_CONNECT) + { + action = IA_NONE; + NetSend(CONN_SYN_N); + phase = 2; + phaseTime = GetTickCount(); + } + + break; + + case 5: + if ((int)(GetTickCount() - phaseTime)/1000 > aliveTimeout) + { + phase = 1; + phaseTime = GetTickCount(); + if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + } + + if (action == IA_CONNECT) + { + action = IA_NONE; + NetSend(CONN_SYN_N); + phase = 2; + phaseTime = GetTickCount(); + } + + break; + } +Sleep(20); +return; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::GetStat(LOADSTAT * ls) +{ +memcpy(ls, &stat, sizeof(stat)); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetServer(const std::string & sn, unsigned short p) +{ +serverName = sn; +port = p; +PrepareNet(); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetLogin(const std::string & l) +{ +login = l; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetPassword(const std::string & p) +{ +password = p; + +unsigned char keyL[IA_PASSWD_LEN]; +memset(keyL, 0, IA_PASSWD_LEN); +strncpy((char *)keyL, password.c_str(), IA_PASSWD_LEN); +Blowfish_Init(&ctxPass, keyL, IA_PASSWD_LEN); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetEnabledDirs(const bool * selectedDirs) +{ +memcpy(IA_CLIENT_PROT::selectedDirs, selectedDirs, sizeof(bool) * DIR_NUM); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Connect() +{ +action = IA_CONNECT; +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Disconnect() +{ +firstConnect = true; +action = IA_DISCONNECT; +return 0; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::GetStrError(std::string * error) const +{ +int ret = codeError; +*error = strError; +strError = ""; +codeError = 0; +return ret; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_CONN_SYN_ACK_8(const char * buffer) +{ +std::vector dirNames; +connSynAck8 = (CONN_SYN_ACK_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(connSynAck8->len); +SwapBytes(connSynAck8->rnd); +SwapBytes(connSynAck8->userTimeOut); +SwapBytes(connSynAck8->aliveDelay); +#endif + +rnd = connSynAck8->rnd; +userTimeout = connSynAck8->userTimeOut; +aliveTimeout = connSynAck8->aliveDelay; + +for (int i = 0; i < DIR_NUM; i++) + { + dirNames.push_back((const char*)connSynAck8->dirName[i]); + } + +if (pDirNameCb != NULL) + pDirNameCb(dirNames, dirNameCbData); + +NetSend(CONN_ACK_N); +phase = 3; +phaseTime = GetTickCount(); + +return CONN_SYN_ACK_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_ALIVE_SYN_8(const char * buffer) +{ +aliveSyn8 = (ALIVE_SYN_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(aliveSyn8->len); +SwapBytes(aliveSyn8->rnd); +SwapBytes(aliveSyn8->cash); +SwapBytes(aliveSyn8->status); +for (int i = 0; i < DIR_NUM; ++i) + { + SwapBytes(aliveSyn8->mu[i]); + SwapBytes(aliveSyn8->md[i]); + SwapBytes(aliveSyn8->su[i]); + SwapBytes(aliveSyn8->sd[i]); + } +#endif + +rnd = aliveSyn8->rnd; +memcpy(&stat, (char*)aliveSyn8->mu, sizeof(stat)); + +if (pStatChangedCb != NULL) + pStatChangedCb(stat, statChangedCbData); + +if (pStatusChangedCb != NULL) + pStatusChangedCb(1, statusChangedCbData); +NetSend(ALIVE_ACK_N); +phaseTime = GetTickCount(); + +return ALIVE_SYN_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_DISCONN_SYN_ACK_8(const char * buffer) +{ +disconnSynAck8 = (DISCONN_SYN_ACK_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(disconnSynAck8->len); +SwapBytes(disconnSynAck8->rnd); +#endif + +rnd = disconnSynAck8->rnd; + +NetSend(DISCONN_ACK_N); +phase = 5; +phaseTime = GetTickCount(); + +return DISCONN_SYN_ACK_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_FIN_8(const char *) +{ +phase = 1; +phaseTime = GetTickCount(); +if (pStatusChangedCb != NULL) + pStatusChangedCb(0, statusChangedCbData); + +return FIN_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_INFO_8(const char * buffer) +{ +info = (INFO_8*)buffer; + +#ifdef ARCH_BE +SwapBytes(info->len); +SwapBytes(info->sendTime); +#endif + +if (pInfoCb != NULL) + pInfoCb((char*)info->text, info->infoType, info->showTime, info->sendTime, infoCbData); +return INFO_8_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Process_ERROR(const char * buffer) +{ +ERR_8 err; +memcpy(&err, buffer, sizeof(err)); + +#ifdef ARCH_BE +SwapBytes(err.len); +#endif + +KOIToWin((const char*)err.text, &messageText); +if (pErrorCb != NULL) + pErrorCb(messageText, IA_SERVER_ERROR, errorCbData); +phase = 1; +phaseTime = GetTickCount(); +codeError = IA_SERVER_ERROR; + +return ERROR_N; +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_CONN_SYN_8(char * buffer) +{ +connSyn8 = (CONN_SYN_8*)buffer; + +assert(sizeof(CONN_SYN_8) == Min8(sizeof(CONN_SYN_8)) && "CONN_SYN_8 is not aligned to 8 bytes"); + +connSyn8->len = sizeof(CONN_SYN_8); + +#ifdef ARCH_BE +SwapBytes(connSyn8->len); +#endif + +strncpy((char*)connSyn8->type, "CONN_SYN", IA_MAX_TYPE_LEN); +strncpy((char*)connSyn8->login, login.c_str(), IA_LOGIN_LEN); +connSyn8->dirs = 0; +for (int i = 0; i < DIR_NUM; i++) + { + connSyn8->dirs |= (selectedDirs[i] << i); + } +return sizeof(CONN_SYN_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_CONN_ACK_8(char * buffer) +{ +connAck8 = (CONN_ACK_8*)buffer; + +assert(sizeof(CONN_ACK_8) == Min8(sizeof(CONN_ACK_8)) && "CONN_ACK_8 is not aligned to 8 bytes"); + +connAck8->len = sizeof(CONN_ACK_8); +strncpy((char*)connAck8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)connAck8->type, "CONN_ACK", IA_MAX_TYPE_LEN); +rnd++; +connAck8->rnd = rnd; + +#ifdef ARCH_BE +SwapBytes(connAck8->len); +SwapBytes(connAck8->rnd); +#endif + +return sizeof(CONN_ACK_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_ALIVE_ACK_8(char * buffer) +{ +aliveAck8 = (ALIVE_ACK_8*)buffer; + +assert(Min8(sizeof(ALIVE_ACK_8)) == sizeof(ALIVE_ACK_8) && "ALIVE_ACK_8 is not aligned to 8 bytes"); + +aliveAck8 = (ALIVE_ACK_8*)buffer; +aliveAck8->len = sizeof(ALIVE_ACK_8); +strncpy((char*)aliveAck8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)aliveAck8->type, "ALIVE_ACK", IA_MAX_TYPE_LEN); +aliveAck8->rnd = ++rnd; + +#ifdef ARCH_BE +SwapBytes(aliveAck8->len); +SwapBytes(aliveAck8->rnd); +#endif + +return sizeof(ALIVE_ACK_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_DISCONN_SYN_8(char * buffer) +{ +disconnSyn8 = (DISCONN_SYN_8*)buffer; + +assert(Min8(sizeof(DISCONN_SYN_8)) == sizeof(DISCONN_SYN_8) && "DISCONN_SYN_8 is not aligned to 8 bytes"); + +disconnSyn8->len = sizeof(DISCONN_SYN_8); + +#ifdef ARCH_BE +SwapBytes(disconnSyn8->len); +#endif + +strncpy((char*)disconnSyn8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)disconnSyn8->type, "DISCONN_SYN", IA_MAX_TYPE_LEN); +strncpy((char*)disconnSyn8->login, login.c_str(), IA_LOGIN_LEN); +return sizeof(DISCONN_SYN_8); +} +//--------------------------------------------------------------------------- +int IA_CLIENT_PROT::Prepare_DISCONN_ACK_8(char * buffer) +{ +disconnAck8 = (DISCONN_ACK_8*)buffer; + +assert(Min8(sizeof(DISCONN_ACK_8)) == sizeof(DISCONN_ACK_8) && "DISCONN_ACK_8 is not aligned to 8 bytes"); + +disconnAck8->len = Min8(sizeof(DISCONN_ACK_8)); +disconnAck8->rnd = rnd + 1; + +#ifdef ARCH_BE +SwapBytes(disconnAck8->len); +SwapBytes(disconnAck8->rnd); +#endif + +strncpy((char*)disconnAck8->loginS, login.c_str(), IA_LOGIN_LEN); +strncpy((char*)disconnAck8->type, "DISCONN_ACK", IA_MAX_TYPE_LEN); +return Min8(sizeof(DISCONN_ACK_8)); +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetStatusChangedCb(tpStatusChangedCb p, void * data) +{ +pStatusChangedCb = p; +statusChangedCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetStatChangedCb(tpStatChangedCb p, void * data) +{ +pStatChangedCb = p; +statChangedCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetInfoCb(tpCallBackInfoFn p, void * data) +{ +pInfoCb = p; +infoCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetDirNameCb(tpCallBackDirNameFn p, void * data) +{ +pDirNameCb = p; +dirNameCbData = data; +} +//--------------------------------------------------------------------------- +void IA_CLIENT_PROT::SetErrorCb(tpCallBackErrorFn p, void * data) +{ +pErrorCb = p; +errorCbData = data; +} +//--------------------------------------------------------------------------- diff --git a/libs/ia/include/stg/ia.h b/libs/ia/include/stg/ia.h new file mode 100644 index 00000000..c37f4394 --- /dev/null +++ b/libs/ia/include/stg/ia.h @@ -0,0 +1,206 @@ +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 1, or (at your option) +** any later version. + +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. + +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + $Author: faust $ + $Revision: 1.10 $ + $Date: 2010/03/15 12:57:24 $ +*/ + +/* +* Author : Boris Mikhailenko +*/ +//--------------------------------------------------------------------------- +#ifndef IA_AUTH_C_H +#define IA_AUTH_C_H + +#ifndef WIN32 +#include +#include +#include +#include +#else +#include +#endif + +#include +#include +#include + +#include "stg/blowfish.h" +#include "stg/ia_packets.h" + +#define IA_BIND_ERROR (1) +#define IA_SERVER_ERROR (2) +#define IA_FCNTL_ERROR (3) +#define IA_GETHOSTBYNAME_ERROR (4) + +#define IA_PROTO_VER (8) +#define IA_PROTO_PROXY_VER (101) + +typedef void (*tpStatusChangedCb)(int status, void * data); +typedef void (*tpStatChangedCb)(const LOADSTAT & stat, void * data); +typedef void (*tpCallBackInfoFn)(const std::string & message, int infoType, int showTime, int sendTime, void * data); +typedef void (*tpCallBackErrorFn)(const std::string & message, int netError, void * data); +typedef void (*tpCallBackDirNameFn)(const std::vector & dirName, void * data); + +//--------------------------------------------------------------------------- +class IA_CLIENT_PROT +{ +#ifdef WIN32 +friend unsigned long WINAPI RunW(void * data); +#else +friend void * RunL(void * data); +#endif + +public: + IA_CLIENT_PROT(const std::string & sn, uint16_t p, const std::string & localName = "", uint16_t localPort = 0); + ~IA_CLIENT_PROT(); + + void Start(); + void Stop(); + void GetStat(LOADSTAT * ls); + + void SetServer(const std::string & sn, unsigned short port); + void SetLogin(const std::string & login); + void SetPassword(const std::string & password); + void SetEnabledDirs(const bool * selectedDirs); + + void SetStatusChangedCb(tpStatusChangedCb p, void * data); + void SetStatChangedCb(tpStatChangedCb p, void * data); + void SetInfoCb(tpCallBackInfoFn p, void * data); + void SetErrorCb(tpCallBackErrorFn p, void * data); + void SetDirNameCb(tpCallBackDirNameFn p, void * data); + + int Connect(); + int Disconnect(); + int GetAuthorized() const { return phase == 3 || phase == 4; }; + int GetPhase() const { return phase; }; + int GetStatus() const; + int GetReconnect() const { return reconnect; }; + void SetReconnect(int r) { reconnect = r; }; + char GetProtoVer() const { return proxyMode ? IA_PROTO_PROXY_VER : IA_PROTO_VER; }; + void GetMessageText(std::string * text) const { *text = messageText; }; + void GetInfoText(std::string * text) const { *text = infoText; }; + int GetStrError(std::string * error) const; + + void SetProxyMode(bool on) { proxyMode = on; }; + bool GetProxyMode() const { return proxyMode; }; + + void SetIP(uint32_t ip) { IA_CLIENT_PROT::ip = ip; }; + uint32_t GetIP() const { return ip; }; + +private: + void Run(); + int NetRecv(); + int NetSend(int n); + bool GetNonstop() const { return nonstop; }; + void PrepareNet(); + int DeterminatePacketType(const char * buffer); + + int Process_CONN_SYN_ACK_8(const char * buffer); + int Process_ALIVE_SYN_8(const char * buffer); + int Process_DISCONN_SYN_ACK_8(const char * buffer); + int Process_FIN_8(const char * buffer); + int Process_INFO_8(const char * buffer); + int Process_ERROR(const char * buffer); + + int Prepare_CONN_SYN_8(char * buffer); + int Prepare_CONN_ACK_8(char * buffer); + int Prepare_ALIVE_ACK_8(char * buffer); + int Prepare_DISCONN_SYN_8(char * buffer); + int Prepare_DISCONN_ACK_8(char * buffer); + + void FillHdr8(char * buffer, unsigned long ip); + int Send(char * buffer, int len); + int Recv(char * buffer, int len); + + LOADSTAT stat; + int action; + int phase; + int phaseTime; + std::string messageText; + std::string infoText; + mutable std::string strError; + mutable int codeError; + bool nonstop; + bool isNetPrepared; + bool proxyMode; + + BLOWFISH_CTX ctxPass; + BLOWFISH_CTX ctxHdr; + + bool selectedDirs[DIR_NUM]; + + std::string password; + std::string login; + + #ifdef WIN32 + WSADATA wsaData; + #else + pthread_t thread; + #endif + + std::string serverName; + uint16_t port; + uint32_t ip; + std::string localName; + uint32_t localIP; + uint32_t localPort; + + struct sockaddr_in servAddr; + + bool firstConnect; + int reconnect; + int sockr; + int protNum; + int userTimeout; + int aliveTimeout; + unsigned int rnd; + + tpStatusChangedCb pStatusChangedCb; + tpStatChangedCb pStatChangedCb; + tpCallBackInfoFn pInfoCb; + tpCallBackErrorFn pErrorCb; + tpCallBackDirNameFn pDirNameCb; + + void * statusChangedCbData; + void * statChangedCbData; + void * infoCbData; + void * errorCbData; + void * dirNameCbData; + + std::map packetTypes; + + CONN_SYN_8 * connSyn8; + CONN_SYN_ACK_8 * connSynAck8; + CONN_ACK_8 * connAck8; + ALIVE_SYN_8 * aliveSyn8; + ALIVE_ACK_8 * aliveAck8; + DISCONN_SYN_8 * disconnSyn8; + DISCONN_SYN_ACK_8 * disconnSynAck8; + DISCONN_ACK_8 * disconnAck8; + INFO_8 * info; +}; +//--------------------------------------------------------------------------- +#ifdef WIN32 +unsigned long WINAPI RunW(void *); +#else +void * RunW(void *); +#endif + +//--------------------------------------------------------------------------- +#endif //IA_AUTH_C_H diff --git a/libs/ibpp/CMakeLists.txt b/libs/ibpp/CMakeLists.txt new file mode 100644 index 00000000..109ba752 --- /dev/null +++ b/libs/ibpp/CMakeLists.txt @@ -0,0 +1,5 @@ +set ( CPP_FILES all_in_one.cpp ) + +add_library ( ibpp STATIC ${CPP_FILES} ) + +target_include_directories ( ibpp PUBLIC include ) diff --git a/libs/ibpp/Makefile b/libs/ibpp/Makefile new file mode 100644 index 00000000..80a895e9 --- /dev/null +++ b/libs/ibpp/Makefile @@ -0,0 +1,33 @@ +############################################################################### +# $Id: Makefile,v 1.6 2009/03/03 15:50:15 faust Exp $ +############################################################################### + +LIB_NAME = stgibpp + +SRCS = array.cpp \ + blob.cpp \ + database.cpp \ + date.cpp \ + dbkey.cpp \ + _dpb.cpp \ + events.cpp \ + exception.cpp \ + _ibpp.cpp \ + _ibs.cpp \ + _rb.cpp \ + row.cpp \ + service.cpp \ + _spb.cpp \ + statement.cpp \ + time.cpp \ + _tpb.cpp \ + transaction.cpp \ + user.cpp + +INCS = ibpp.h + +LIB_DEFS = -DIBPP_LINUX + +LIBS = -lfbclient + +include ../Makefile.in diff --git a/libs/ibpp/_dpb.cpp b/libs/ibpp/_dpb.cpp new file mode 100644 index 00000000..4729cd3c --- /dev/null +++ b/libs/ibpp/_dpb.cpp @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: _dpb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $ +// Subject : IBPP, internal DPB class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * DPB == Database Parameter Block/Buffer, see Interbase 6.0 C-API +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +const int DPB::BUFFERINCR = 128; + +void DPB::Grow(int needed) +{ + if (mBuffer == 0) ++needed; // Initial alloc will require one more byte + if ((mSize + needed) > mAlloc) + { + // We need to grow the buffer. We use increments of BUFFERINCR bytes. + needed = (needed / BUFFERINCR + 1) * BUFFERINCR; + char* newbuffer = new char[mAlloc + needed]; + if (mBuffer == 0) + { + // Initial allocation, initialize the version tag + newbuffer[0] = isc_dpb_version1; + mSize = 1; + } + else + { + // Move the old buffer content to the new one + memcpy(newbuffer, mBuffer, mSize); + delete [] mBuffer; + } + mBuffer = newbuffer; + mAlloc += needed; + } +} + +void DPB::Insert(char type, const char* data) +{ + int len = (int)strlen(data); + Grow(len + 2); + mBuffer[mSize++] = type; + mBuffer[mSize++] = char(len); + strncpy(&mBuffer[mSize], data, len); + mSize += len; +} + +void DPB::Insert(char type, int16_t data) +{ + Grow(2 + 2); + mBuffer[mSize++] = type; + mBuffer[mSize++] = char(2); + *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&data, 2)); + mSize += 2; +} + +void DPB::Insert(char type, bool data) +{ + Grow(2 + 1); + mBuffer[mSize++] = type; + mBuffer[mSize++] = char(1); + mBuffer[mSize++] = char(data ? 1 : 0); +} + +void DPB::Insert(char type, char data) +{ + Grow(2 + 1); + mBuffer[mSize++] = type; + mBuffer[mSize++] = char(1); + mBuffer[mSize++] = data; +} + +void DPB::Reset() +{ + if (mAlloc != 0) + { + delete [] mBuffer; + mBuffer = 0; + mSize = 0; + mAlloc = 0; + } +} + +// +// EOF +// diff --git a/libs/ibpp/_ibpp.cpp b/libs/ibpp/_ibpp.cpp new file mode 100644 index 00000000..3374b966 --- /dev/null +++ b/libs/ibpp/_ibpp.cpp @@ -0,0 +1,367 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: _ibpp.cpp,v 1.3 2009/03/19 20:00:27 faust Exp $ +// Subject : IBPP, Initialization of the library +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +#ifdef IBPP_WINDOWS +// New (optional) Registry Keys introduced by Firebird Server 1.5 +#define REG_KEY_ROOT_INSTANCES "SOFTWARE\\Firebird Project\\Firebird Server\\Instances" +#define FB_DEFAULT_INSTANCE "DefaultInstance" +#endif + +namespace ibpp_internals +{ + const double consts::dscales[19] = { + 1, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, + 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15, + 1E16, 1E17, 1E18 }; + + const int consts::Dec31_1899 = 693595; + +// Many compilers confuses those following min/max with macros min and max ! +#undef min +#undef max + +#ifdef __DMC__ // Needs to break-down the declaration else compiler crash (!) + const std::numeric_limits i16_limits; + const std::numeric_limits i32_limits; + const int16_t consts::min16 = i16_limits.min(); + const int16_t consts::max16 = i16_limits.max(); + const int32_t consts::min32 = i32_limits.min(); + const int32_t consts::max32 = i32_limits.max(); +#else + const int16_t consts::min16 = std::numeric_limits::min(); + const int16_t consts::max16 = std::numeric_limits::max(); + const int32_t consts::min32 = std::numeric_limits::min(); + const int32_t consts::max32 = std::numeric_limits::max(); +#endif + + GDS gds; // Global unique GDS instance + +#ifdef IBPP_WINDOWS + std::string AppPath; // Used by GDS::Call() below +#endif + +#ifdef _DEBUG + std::ostream& operator<< (std::ostream& a, flush_debug_stream_type) + { + if (std::stringstream* p = dynamic_cast(&a)) + { +#ifdef IBPP_WINDOWS + ::OutputDebugString(("IBPP: " + p->str() + "\n").c_str()); +#endif + p->str(""); + } + return a; + } +#endif // _DEBUG + +} + +using namespace ibpp_internals; + +GDS* GDS::Call() +{ + // Let's load the CLIENT library, if it is not already loaded. + // The load is guaranteed to be done only once per application. + + if (! mReady) + { +#ifdef IBPP_WINDOWS + + // Let's load the FBCLIENT.DLL or GDS32.DLL, we will never release it. + // Windows will do that for us when the executable will terminate. + + char fbdll[MAX_PATH]; + HKEY hkey_instances; + + // Try to load FBCLIENT.DLL from each of the additional optional paths + // that may have been specified through ClientLibSearchPaths(). + // We also want to actually update the environment PATH so that it references + // the specific path from where we attempt the load. This is useful because + // it directs the system to attempt finding dependencies (like the C/C++ + // runtime libraries) from the same location where FBCLIENT is found. + + mHandle = 0; + + std::string SysPath(getenv("PATH")); + std::string::size_type pos = 0; + while (pos < mSearchPaths.size()) + { + std::string::size_type newpos = mSearchPaths.find(';', pos); + + std::string path; + if (newpos == std::string::npos) path = mSearchPaths.substr(pos); + else path = mSearchPaths.substr(pos, newpos-pos); + + if (path.size() >= 1) + { + if (path[path.size()-1] != '\\') path += '\\'; + + AppPath.assign("PATH="); + AppPath.append(path).append(";").append(SysPath); + putenv(AppPath.c_str()); + + path.append("fbclient.dll"); + mHandle = LoadLibrary(path.c_str()); + if (mHandle != 0 || newpos == std::string::npos) break; + } + pos = newpos + 1; + } + + if (mHandle == 0) + { + // Try to load FBCLIENT.DLL from the current application location. This + // is a usefull step for applications using the embedded version of FB + // or a local copy (for whatever reasons) of the dll. + + if (! AppPath.empty()) + { + // Restores the original system path + AppPath.assign("PATH="); + AppPath.append(SysPath); + putenv(AppPath.c_str()); + } + + int len = GetModuleFileName(NULL, fbdll, sizeof(fbdll)); + if (len != 0) + { + // Get to the last '\' (this one precedes the filename part). + // There is always one after a success call to GetModuleFileName(). + char* p = fbdll + len; + do {--p;} while (*p != '\\'); + *p = '\0'; + lstrcat(fbdll, "\\fbembed.dll");// Local copy could be named fbembed.dll + mHandle = LoadLibrary(fbdll); + if (mHandle == 0) + { + *p = '\0'; + lstrcat(fbdll, "\\fbclient.dll"); // Or possibly renamed fbclient.dll + mHandle = LoadLibrary(fbdll); + } + } + } + + if (mHandle == 0) + { + // Try to locate FBCLIENT.DLL through the optional FB registry key. + + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REG_KEY_ROOT_INSTANCES, 0, + KEY_READ, &hkey_instances) == ERROR_SUCCESS) + { + DWORD keytype; + DWORD buflen = sizeof(fbdll); + if (RegQueryValueEx(hkey_instances, FB_DEFAULT_INSTANCE, 0, + &keytype, reinterpret_cast(fbdll), + &buflen) == ERROR_SUCCESS && keytype == REG_SZ) + { + lstrcat(fbdll, "bin\\fbclient.dll"); + mHandle = LoadLibrary(fbdll); + } + RegCloseKey(hkey_instances); + } + } + + if (mHandle == 0) + { + // Let's try from the PATH and System directories + mHandle = LoadLibrary("fbclient.dll"); + if (mHandle == 0) + { + // Not found. Last try : attemps loading gds32.dll from PATH and + // System directories + mHandle = LoadLibrary("gds32.dll"); + if (mHandle == 0) + throw LogicExceptionImpl("GDS::Call()", + _("Can't find or load FBCLIENT.DLL or GDS32.DLL")); + } + } +#endif + + mGDSVersion = 60; + + // Get the entry points that we need + +#ifdef IBPP_WINDOWS +#define IB_ENTRYPOINT(X) \ + if ((m_##X = (proto_##X*)GetProcAddress(mHandle, "isc_"#X)) == 0) \ + throw LogicExceptionImpl("GDS:gds()", _("Entry-point isc_"#X" not found")) +#endif +#ifdef IBPP_UNIX +/* TODO : perform a late-bind on unix --- not so important, well I think (OM) */ +#define IB_ENTRYPOINT(X) m_##X = (proto_##X*)isc_##X +#endif + + IB_ENTRYPOINT(create_database); + IB_ENTRYPOINT(attach_database); + IB_ENTRYPOINT(detach_database); + IB_ENTRYPOINT(drop_database); + IB_ENTRYPOINT(database_info); + IB_ENTRYPOINT(open_blob2); + IB_ENTRYPOINT(create_blob2); + IB_ENTRYPOINT(close_blob); + IB_ENTRYPOINT(cancel_blob); + IB_ENTRYPOINT(get_segment); + IB_ENTRYPOINT(put_segment); + IB_ENTRYPOINT(blob_info); + IB_ENTRYPOINT(array_lookup_bounds); + IB_ENTRYPOINT(array_get_slice); + IB_ENTRYPOINT(array_put_slice); + IB_ENTRYPOINT(vax_integer); + IB_ENTRYPOINT(sqlcode); + IB_ENTRYPOINT(sql_interprete); + IB_ENTRYPOINT(interprete); + IB_ENTRYPOINT(que_events); + IB_ENTRYPOINT(cancel_events); + IB_ENTRYPOINT(start_multiple); + IB_ENTRYPOINT(commit_transaction); + IB_ENTRYPOINT(commit_retaining); + IB_ENTRYPOINT(rollback_transaction); + IB_ENTRYPOINT(rollback_retaining); + IB_ENTRYPOINT(dsql_execute_immediate); + IB_ENTRYPOINT(dsql_allocate_statement); + IB_ENTRYPOINT(dsql_describe); + IB_ENTRYPOINT(dsql_describe_bind); + IB_ENTRYPOINT(dsql_prepare); + IB_ENTRYPOINT(dsql_execute); + IB_ENTRYPOINT(dsql_execute2); + IB_ENTRYPOINT(dsql_fetch); + IB_ENTRYPOINT(dsql_free_statement); + IB_ENTRYPOINT(dsql_set_cursor_name); + IB_ENTRYPOINT(dsql_sql_info); + + IB_ENTRYPOINT(service_attach); + IB_ENTRYPOINT(service_detach); + IB_ENTRYPOINT(service_start); + IB_ENTRYPOINT(service_query); + + mReady = true; + } + + return this; +} + +namespace IBPP +{ + + bool CheckVersion(uint32_t AppVersion) + { + //(void)gds.Call(); // Just call it to trigger the initialization + return (AppVersion & 0xFFFFFF00) == + (IBPP::Version & 0xFFFFFF00) ? true : false; + } + + int GDSVersion() + { + return gds.Call()->mGDSVersion; + } + +#ifdef IBPP_WINDOWS + void ClientLibSearchPaths(const std::string& paths) + { + gds.mSearchPaths.assign(paths); + } +#else + void ClientLibSearchPaths(const std::string&) + { + } +#endif + + // Factories for our Interface objects + + Service ServiceFactory(const std::string& ServerName, + const std::string& UserName, const std::string& UserPassword) + { + (void)gds.Call(); // Triggers the initialization, if needed + return new ServiceImpl(ServerName, UserName, UserPassword); + } + + Database DatabaseFactory(const std::string& ServerName, + const std::string& DatabaseName, const std::string& UserName, + const std::string& UserPassword, const std::string& RoleName, + const std::string& CharSet, const std::string& CreateParams) + { + (void)gds.Call(); // Triggers the initialization, if needed + return new DatabaseImpl(ServerName, DatabaseName, UserName, + UserPassword, RoleName, CharSet, CreateParams); + } + + Transaction TransactionFactory(Database db, TAM am, + TIL il, TLR lr, TFF flags) + { + (void)gds.Call(); // Triggers the initialization, if needed + return new TransactionImpl( dynamic_cast(db.intf()), + am, il, lr, flags); + } + + Statement StatementFactory(Database db, Transaction tr, + const std::string& sql) + { + (void)gds.Call(); // Triggers the initialization, if needed + return new StatementImpl( dynamic_cast(db.intf()), + dynamic_cast(tr.intf()), + sql); + } + + Blob BlobFactory(Database db, Transaction tr) + { + (void)gds.Call(); // Triggers the initialization, if needed + return new BlobImpl(dynamic_cast(db.intf()), + dynamic_cast(tr.intf())); + } + + Array ArrayFactory(Database db, Transaction tr) + { + (void)gds.Call(); // Triggers the initialization, if needed + return new ArrayImpl(dynamic_cast(db.intf()), + dynamic_cast(tr.intf())); + } + + Events EventsFactory(Database db) + { + (void)gds.Call(); // Triggers the initialization, if needed + return new EventsImpl(dynamic_cast(db.intf())); + } + +} + +// +// EOF +// + diff --git a/libs/ibpp/_ibpp.h b/libs/ibpp/_ibpp.h new file mode 100644 index 00000000..27d368af --- /dev/null +++ b/libs/ibpp/_ibpp.h @@ -0,0 +1,1414 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: _ibpp.h,v 1.2 2007/05/17 08:37:05 faust Exp $ +// Subject : IBPP internal declarations +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// +// * 'Internal declarations' means everything used to implement ibpp. This +// file and its contents is NOT needed by users of the library. All those +// declarations are wrapped in a namespace : 'ibpp_internals'. +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __INTERNAL_IBPP_H__ +#define __INTERNAL_IBPP_H__ + +#include "stg/ibpp.h" + +#if defined(__BCPLUSPLUS__) || defined(_MSC_VER) || defined(__DMC__) +#define HAS_HDRSTOP +#endif + +#if (defined(__GNUC__) && defined(IBPP_WINDOWS)) +// Setting flags for ibase.h -- using GCC/Cygwin/MinGW on Win32 +#ifndef _MSC_VER +#define _MSC_VER 1299 +#endif +#ifndef _WIN32 +#define _WIN32 1 +#endif +#endif + +#include "ibase.h" // From Firebird 1.x or InterBase 6.x installation + +#if (defined(__GNUC__) && defined(IBPP_WINDOWS)) +// UNSETTING flags used above for ibase.h -- Huge conflicts with libstdc++ ! +#undef _MSC_VER +#undef _WIN32 +#endif + +#ifdef IBPP_WINDOWS +#include +#endif + +//#include +#include +#include +#include +#include + +#ifdef _DEBUG +#define ASSERTION(x) {if (!(x)) {throw LogicExceptionImpl("ASSERTION", \ + "'"#x"' is not verified at %s, line %d", \ + __FILE__, __LINE__);}} +#else +#define ASSERTION(x) /* x */ +#endif + +// Fix to famous MSVC 6 variable scope bug +#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300 +#define for if(true)for +#endif + +namespace ibpp_internals +{ + +enum flush_debug_stream_type {fds}; + +#ifdef _DEBUG + +struct DebugStream : public std::stringstream +{ + // next two operators fix some g++ and vc++ related problems + std::ostream& operator<< (const char* p) + { static_cast(*this)<< p; return *this; } + + std::ostream& operator<< (const std::string& p) + { static_cast(*this)<< p; return *this; } + + DebugStream& operator=(const DebugStream&) {return *this;} + DebugStream(const DebugStream&) {} + DebugStream() {} +}; +std::ostream& operator<< (std::ostream& a, flush_debug_stream_type); + +#else + +struct DebugStream +{ + template DebugStream& operator<< (const T&) { return *this; } + // for manipulators + DebugStream& operator<< (std::ostream&(*)(std::ostream&)) { return *this; } +}; + +#endif // _DEBUG + +class DatabaseImpl; +class TransactionImpl; +class StatementImpl; +class BlobImpl; +class ArrayImpl; +class EventsImpl; + +// Native data types +typedef enum {ivArray, ivBlob, ivDate, ivTime, ivTimestamp, ivString, + ivInt16, ivInt32, ivInt64, ivFloat, ivDouble, + ivBool, ivDBKey, ivByte} IITYPE; + +// +// Those are the Interbase C API prototypes that we use +// Taken 'asis' from IBASE.H, prefix 'isc_' replaced with 'proto_', +// and 'typedef' preprended... +// + +typedef ISC_STATUS ISC_EXPORT proto_create_database (ISC_STATUS *, + short, + char *, + isc_db_handle *, + short, + char *, + short); + +typedef ISC_STATUS ISC_EXPORT proto_attach_database (ISC_STATUS *, + short, + char *, + isc_db_handle *, + short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_detach_database (ISC_STATUS *, + isc_db_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_drop_database (ISC_STATUS *, + isc_db_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_database_info (ISC_STATUS *, + isc_db_handle *, + short, + char *, + short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_execute_immediate (ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned short, + char *, + unsigned short, + XSQLDA *); + +typedef ISC_STATUS ISC_EXPORT proto_open_blob2 (ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + isc_blob_handle *, + ISC_QUAD *, + short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_create_blob2 (ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + isc_blob_handle *, + ISC_QUAD *, + short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_close_blob (ISC_STATUS *, + isc_blob_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_cancel_blob (ISC_STATUS *, + isc_blob_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_get_segment (ISC_STATUS *, + isc_blob_handle *, + unsigned short *, + unsigned short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_put_segment (ISC_STATUS *, + isc_blob_handle *, + unsigned short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_blob_info (ISC_STATUS *, + isc_blob_handle *, + short, + char *, + short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_array_lookup_bounds (ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + char *, + char *, + ISC_ARRAY_DESC *); + +typedef ISC_STATUS ISC_EXPORT proto_array_get_slice (ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + ISC_QUAD *, + ISC_ARRAY_DESC *, + void *, + ISC_LONG *); + +typedef ISC_STATUS ISC_EXPORT proto_array_put_slice (ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + ISC_QUAD *, + ISC_ARRAY_DESC *, + void *, + ISC_LONG *); + +typedef ISC_LONG ISC_EXPORT proto_vax_integer (char *, + short); + +typedef ISC_LONG ISC_EXPORT proto_sqlcode (ISC_STATUS *); + +typedef void ISC_EXPORT proto_sql_interprete (short, + char *, + short); + +typedef ISC_STATUS ISC_EXPORT proto_interprete (char *, + ISC_STATUS * *); + +typedef ISC_STATUS ISC_EXPORT proto_que_events (ISC_STATUS *, + isc_db_handle *, + ISC_LONG *, + short, + char *, + isc_callback, + void *); + +typedef ISC_STATUS ISC_EXPORT proto_cancel_events (ISC_STATUS *, + isc_db_handle *, + ISC_LONG *); + +typedef ISC_STATUS ISC_EXPORT proto_start_multiple (ISC_STATUS *, + isc_tr_handle *, + short, + void *); + +typedef ISC_STATUS ISC_EXPORT proto_commit_transaction (ISC_STATUS *, + isc_tr_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_commit_retaining (ISC_STATUS *, + isc_tr_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_rollback_transaction (ISC_STATUS *, + isc_tr_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_rollback_retaining (ISC_STATUS *, + isc_tr_handle *); + +/////////// +typedef ISC_STATUS ISC_EXPORT proto_dsql_allocate_statement (ISC_STATUS *, + isc_db_handle *, + isc_stmt_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_describe (ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_describe_bind (ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_execute (ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_execute2 (ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + XSQLDA *, + XSQLDA *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_fetch (ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_free_statement (ISC_STATUS *, + isc_stmt_handle *, + unsigned short); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_prepare (ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + char *, + unsigned short, + XSQLDA *); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_set_cursor_name (ISC_STATUS *, + isc_stmt_handle *, + char *, + unsigned short); + +typedef ISC_STATUS ISC_EXPORT proto_dsql_sql_info (ISC_STATUS *, + isc_stmt_handle *, + short, + char *, + short, + char *); + +typedef void ISC_EXPORT proto_decode_date (ISC_QUAD *, + void *); + +typedef void ISC_EXPORT proto_encode_date (void *, + ISC_QUAD *); + +typedef int ISC_EXPORT proto_add_user (ISC_STATUS *, USER_SEC_DATA *); +typedef int ISC_EXPORT proto_delete_user (ISC_STATUS *, USER_SEC_DATA *); +typedef int ISC_EXPORT proto_modify_user (ISC_STATUS *, USER_SEC_DATA *); + +// +// Those API are only available in versions 6.x of the GDS32.DLL +// + +typedef ISC_STATUS ISC_EXPORT proto_service_attach (ISC_STATUS *, + unsigned short, + char *, + isc_svc_handle *, + unsigned short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_service_detach (ISC_STATUS *, + isc_svc_handle *); + +typedef ISC_STATUS ISC_EXPORT proto_service_query (ISC_STATUS *, + isc_svc_handle *, + isc_resv_handle *, + unsigned short, + char *, + unsigned short, + char *, + unsigned short, + char *); + +typedef ISC_STATUS ISC_EXPORT proto_service_start (ISC_STATUS *, + isc_svc_handle *, + isc_resv_handle *, + unsigned short, + char*); + +typedef void ISC_EXPORT proto_decode_sql_date (ISC_DATE *, + void *); + +typedef void ISC_EXPORT proto_decode_sql_time (ISC_TIME *, + void *); + +typedef void ISC_EXPORT proto_decode_timestamp (ISC_TIMESTAMP *, + void *); + +typedef void ISC_EXPORT proto_encode_sql_date (void *, + ISC_DATE *); + +typedef void ISC_EXPORT proto_encode_sql_time (void *, + ISC_TIME *); + +typedef void ISC_EXPORT proto_encode_timestamp (void *, + ISC_TIMESTAMP *); + +// +// Internal binding structure to the GDS32 DLL +// + +struct GDS +{ + // Attributes + bool mReady; + int mGDSVersion; // Version of the GDS32.DLL (50 for 5.0, 60 for 6.0) + +#ifdef IBPP_WINDOWS + HMODULE mHandle; // The GDS32.DLL HMODULE + std::string mSearchPaths; // Optional additional search paths +#endif + + GDS* Call(); + + // GDS32 Entry Points + proto_create_database* m_create_database; + proto_attach_database* m_attach_database; + proto_detach_database* m_detach_database; + proto_drop_database* m_drop_database; + proto_database_info* m_database_info; + proto_dsql_execute_immediate* m_dsql_execute_immediate; + proto_open_blob2* m_open_blob2; + proto_create_blob2* m_create_blob2; + proto_close_blob* m_close_blob; + proto_cancel_blob* m_cancel_blob; + proto_get_segment* m_get_segment; + proto_put_segment* m_put_segment; + proto_blob_info* m_blob_info; + proto_array_lookup_bounds* m_array_lookup_bounds; + proto_array_get_slice* m_array_get_slice; + proto_array_put_slice* m_array_put_slice; + + proto_vax_integer* m_vax_integer; + proto_sqlcode* m_sqlcode; + proto_sql_interprete* m_sql_interprete; + proto_interprete* m_interprete; + proto_que_events* m_que_events; + proto_cancel_events* m_cancel_events; + proto_start_multiple* m_start_multiple; + proto_commit_transaction* m_commit_transaction; + proto_commit_retaining* m_commit_retaining; + proto_rollback_transaction* m_rollback_transaction; + proto_rollback_retaining* m_rollback_retaining; + proto_dsql_allocate_statement* m_dsql_allocate_statement; + proto_dsql_describe* m_dsql_describe; + proto_dsql_describe_bind* m_dsql_describe_bind; + proto_dsql_prepare* m_dsql_prepare; + proto_dsql_execute* m_dsql_execute; + proto_dsql_execute2* m_dsql_execute2; + proto_dsql_fetch* m_dsql_fetch; + proto_dsql_free_statement* m_dsql_free_statement; + proto_dsql_set_cursor_name* m_dsql_set_cursor_name; + proto_dsql_sql_info* m_dsql_sql_info; + //proto_decode_date* m_decode_date; + //proto_encode_date* m_encode_date; + //proto_add_user* m_add_user; + //proto_delete_user* m_delete_user; + //proto_modify_user* m_modify_user; + + proto_service_attach* m_service_attach; + proto_service_detach* m_service_detach; + proto_service_start* m_service_start; + proto_service_query* m_service_query; + //proto_decode_sql_date* m_decode_sql_date; + //proto_decode_sql_time* m_decode_sql_time; + //proto_decode_timestamp* m_decode_timestamp; + //proto_encode_sql_date* m_encode_sql_date; + //proto_encode_sql_time* m_encode_sql_time; + //proto_encode_timestamp* m_encode_timestamp; + + // Constructor (No need for a specific destructor) + GDS() + { + mReady = false; + mGDSVersion = 0; +#ifdef IBPP_WINDOWS + mHandle = 0; +#endif + } +}; + +extern GDS gds; + +// +// Service Parameter Block (used to define a service) +// + +class SPB +{ + static const int BUFFERINCR; + + char* mBuffer; // Dynamically allocated SPB structure + int mSize; // Its used size in bytes + int mAlloc; // Its allocated size in bytes + + void Grow(int needed); // Alloc or grow the mBuffer + +public: + void Insert(char); // Insert a single byte code + void InsertString(char, int, const char*); // Insert a string, len can be defined as 1 or 2 bytes + void InsertByte(char type, char data); + void InsertQuad(char type, int32_t data); + void Reset(); // Clears the SPB + char* Self() { return mBuffer; } + short Size() { return (short)mSize; } + + SPB() : mBuffer(0), mSize(0), mAlloc(0) { } + ~SPB() { Reset(); } +}; + +// +// Database Parameter Block (used to define a database) +// + +class DPB +{ + static const int BUFFERINCR; + + char* mBuffer; // Dynamically allocated DPB structure + int mSize; // Its used size in bytes + int mAlloc; // Its allocated size in bytes + + void Grow(int needed); // Allocate or grow the mBuffer, so that + // 'needed' bytes can be written (at least) + +public: + void Insert(char, const char*); // Insert a new char* 'cluster' + void Insert(char, int16_t); // Insert a new int16_t 'cluster' + void Insert(char, bool); // Insert a new bool 'cluster' + void Insert(char, char); // Insert a new byte 'cluster' + void Reset(); // Clears the DPB + char* Self() { return mBuffer; } + short Size() { return (short)mSize; } + + DPB() : mBuffer(0), mSize(0), mAlloc(0) { } + ~DPB() { Reset(); } +}; + +// +// Transaction Parameter Block (used to define a transaction) +// + +class TPB +{ + static const int BUFFERINCR; + + char* mBuffer; // Dynamically allocated TPB structure + int mSize; // Its used size in bytes + int mAlloc; // Its allocated size + + void Grow(int needed); // Alloc or re-alloc the mBuffer + +public: + void Insert(char); // Insert a flag item + void Insert(const std::string& data); // Insert a string (typically table name) + void Reset(); // Clears the TPB + char* Self() { return mBuffer; } + int Size() { return mSize; } + + TPB() : mBuffer(0), mSize(0), mAlloc(0) { } + ~TPB() { Reset(); } +}; + +// +// Used to receive (and process) a results buffer in various API calls +// + +class RB +{ + char* mBuffer; + int mSize; + + char* FindToken(char token); + char* FindToken(char token, char subtoken); + +public: + void Reset(); + int GetValue(char token); + int GetCountValue(char token); + int GetValue(char token, char subtoken); + bool GetBool(char token); + int GetString(char token, std::string& data); + + char* Self() { return mBuffer; } + short Size() { return (short)mSize; } + + RB(); + RB(int Size); + ~RB(); +}; + +// +// Used to receive status info from API calls +// + +class IBS +{ + mutable ISC_STATUS mVector[20]; + mutable std::string mMessage; + +public: + ISC_STATUS* Self() { return mVector; } + bool Errors() { return (mVector[0] == 1 && mVector[1] > 0) ? true : false; } + const char* ErrorMessage() const; + int SqlCode() const; + int EngineCode() const { return (mVector[0] == 1) ? (int)mVector[1] : 0; } + void Reset(); + + IBS(); + IBS(IBS&); // Copy Constructor + ~IBS(); +}; + +/////////////////////////////////////////////////////////////////////////////// +// +// Implementation of the "hidden" classes associated with their public +// counterparts. Their private data and methods can freely change without +// breaking the compatibility of the DLL. If they receive new public methods, +// and those methods are reflected in the public class, then the compatibility +// is broken. +// +/////////////////////////////////////////////////////////////////////////////// + +// +// Hidden implementation of Exception classes. +// + +/* + std::exception + | + IBPP::Exception + / \ + / \ + IBPP::LogicException ExceptionBase IBPP::SQLException + | \ / | \ / + | LogicExceptionImpl | SQLExceptionImpl + | | + IBPP::WrongType | + \ | + IBPP::WrongTypeImpl +*/ + +class ExceptionBase +{ + // (((((((( OBJECT INTERNALS )))))))) + +protected: + std::string mContext; // Exception context ("IDatabase::Drop") + std::string mWhat; // Full formatted message + + void buildErrorMessage(const char* message); + void raise(const std::string& context, const char* message, va_list argptr); + +public: + // The following constructors are small and could be inlined, but for object + // code compacity of the library it is much better to have them non-inlined. + // The amount of code generated by compilers for a throw is well-enough. + + ExceptionBase() throw(); + ExceptionBase(const ExceptionBase& copied) throw(); + ExceptionBase& operator=(const ExceptionBase& copied) throw(); + ExceptionBase(const std::string& context, const char* message = 0, ...) throw(); + + virtual ~ExceptionBase() throw(); + + // (((((((( OBJECT INTERFACE )))))))) + + virtual const char* Origin() const throw(); + virtual const char* ErrorMessage() const throw(); + virtual const char* what() const throw(); +}; + +class LogicExceptionImpl : public IBPP::LogicException, public ExceptionBase +{ + // (((((((( OBJECT INTERNALS )))))))) + +public: + // The following constructors are small and could be inlined, but for object + // code compacity of the library it is much better to have them non-inlined. + // The amount of code generated by compilers for a throw is well-enough. + + LogicExceptionImpl() throw(); + LogicExceptionImpl(const LogicExceptionImpl& copied) throw(); + LogicExceptionImpl& operator=(const LogicExceptionImpl& copied) throw(); + LogicExceptionImpl(const std::string& context, const char* message = 0, ...) throw(); + + virtual ~LogicExceptionImpl() throw (); + + // (((((((( OBJECT INTERFACE )))))))) + // + // The object public interface is partly implemented by inheriting from + // the ExceptionBase class. + +public: + virtual const char* Origin() const throw(); + virtual const char* ErrorMessage() const throw(); + virtual const char* what() const throw(); +}; + +class SQLExceptionImpl : public IBPP::SQLException, public ExceptionBase +{ + // (((((((( OBJECT INTERNALS )))))))) + +private: + int mSqlCode; + int mEngineCode; + +public: + // The following constructors are small and could be inlined, but for object + // code compacity of the library it is much better to have them non-inlined. + // The amount of code generated by compilers for a throw is well-enough. + + SQLExceptionImpl() throw(); + SQLExceptionImpl(const SQLExceptionImpl& copied) throw(); + SQLExceptionImpl& operator=(const SQLExceptionImpl& copied) throw(); + SQLExceptionImpl(const IBS& status, const std::string& context, + const char* message = 0, ...) throw(); + + virtual ~SQLExceptionImpl() throw (); + + // (((((((( OBJECT INTERFACE )))))))) + // + // The object public interface is partly implemented by inheriting from + // the ExceptionBase class. + +public: + virtual const char* Origin() const throw(); + virtual const char* ErrorMessage() const throw(); + virtual const char* what() const throw(); + virtual int SqlCode() const throw(); + virtual int EngineCode() const throw(); +}; + +class WrongTypeImpl : public IBPP::WrongType, public ExceptionBase +{ + // (((((((( OBJECT INTERNALS )))))))) + +public: + // The following constructors are small and could be inlined, but for object + // code compacity of the library it is much better to have them non-inlined. + // The amount of code generated by compilers for a throw is well-enough. + + WrongTypeImpl() throw(); + WrongTypeImpl(const WrongTypeImpl& copied) throw(); + WrongTypeImpl& operator=(const WrongTypeImpl& copied) throw(); + WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType, + const char* message = 0, ...) throw(); + + virtual ~WrongTypeImpl() throw (); + + // (((((((( OBJECT INTERFACE )))))))) + // + // The object public interface is partly implemented by inheriting from + // the ExceptionBase class. + +public: + virtual const char* Origin() const throw(); + virtual const char* ErrorMessage() const throw(); + virtual const char* what() const throw(); +}; + +class ServiceImpl : public IBPP::IService +{ + // (((((((( OBJECT INTERNALS )))))))) + +private: + int mRefCount; // Reference counter + isc_svc_handle mHandle; // InterBase API Service Handle + std::string mServerName; // Nom du serveur + std::string mUserName; // Nom de l'utilisateur + std::string mUserPassword; // Mot de passe de l'utilisateur + std::string mWaitMessage; // Progress message returned by WaitMsg() + + isc_svc_handle* GetHandlePtr() { return &mHandle; } + void SetServerName(const char*); + void SetUserName(const char*); + void SetUserPassword(const char*); + +public: + isc_svc_handle GetHandle() { return mHandle; } + + ServiceImpl(const std::string& ServerName, const std::string& UserName, + const std::string& UserPassword); + ~ServiceImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + void Connect(); + bool Connected() { return mHandle == 0 ? false : true; } + void Disconnect(); + + void GetVersion(std::string& version); + + void AddUser(const IBPP::User&); + void GetUser(IBPP::User&); + void GetUsers(std::vector&); + void ModifyUser(const IBPP::User&); + void RemoveUser(const std::string& username); + + void SetPageBuffers(const std::string& dbfile, int buffers); + void SetSweepInterval(const std::string& dbfile, int sweep); + void SetSyncWrite(const std::string& dbfile, bool); + void SetReadOnly(const std::string& dbfile, bool); + void SetReserveSpace(const std::string& dbfile, bool); + + void Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout); + void Restart(const std::string& dbfile); + void Sweep(const std::string& dbfile); + void Repair(const std::string& dbfile, IBPP::RPF flags); + + void StartBackup(const std::string& dbfile, const std::string& bkfile, + IBPP::BRF flags = IBPP::BRF(0)); + void StartRestore(const std::string& bkfile, const std::string& dbfile, + int pagesize, IBPP::BRF flags = IBPP::BRF(0)); + + const char* WaitMsg(); + void Wait(); + + IBPP::IService* AddRef(); + void Release(); +}; + +class DatabaseImpl : public IBPP::IDatabase +{ + // (((((((( OBJECT INTERNALS )))))))) + + int mRefCount; // Reference counter + isc_db_handle mHandle; // InterBase API Session Handle + std::string mServerName; // Server name + std::string mDatabaseName; // Database name (path/file) + std::string mUserName; // User name + std::string mUserPassword; // User password + std::string mRoleName; // Role used for the duration of the connection + std::string mCharSet; // Character Set used for the connection + std::string mCreateParams; // Other parameters (creation only) + + int mDialect; // 1 if IB5, 1 or 3 if IB6/FB1 + std::vector mTransactions;// Table of Transaction* + std::vector mStatements;// Table of Statement* + std::vector mBlobs; // Table of Blob* + std::vector mArrays; // Table of Array* + std::vector mEvents; // Table of Events* + +public: + isc_db_handle* GetHandlePtr() { return &mHandle; } + isc_db_handle GetHandle() { return mHandle; } + + void AttachTransactionImpl(TransactionImpl*); + void DetachTransactionImpl(TransactionImpl*); + void AttachStatementImpl(StatementImpl*); + void DetachStatementImpl(StatementImpl*); + void AttachBlobImpl(BlobImpl*); + void DetachBlobImpl(BlobImpl*); + void AttachArrayImpl(ArrayImpl*); + void DetachArrayImpl(ArrayImpl*); + void AttachEventsImpl(EventsImpl*); + void DetachEventsImpl(EventsImpl*); + + DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName, + const std::string& UserName, const std::string& UserPassword, + const std::string& RoleName, const std::string& CharSet, + const std::string& CreateParams); + ~DatabaseImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + const char* ServerName() const { return mServerName.c_str(); } + const char* DatabaseName() const { return mDatabaseName.c_str(); } + const char* Username() const { return mUserName.c_str(); } + const char* UserPassword() const { return mUserPassword.c_str(); } + const char* RoleName() const { return mRoleName.c_str(); } + const char* CharSet() const { return mCharSet.c_str(); } + const char* CreateParams() const { return mCreateParams.c_str(); } + + void Info(int* ODSMajor, int* ODSMinor, + int* PageSize, int* Pages, int* Buffers, int* Sweep, + bool* SyncWrites, bool* Reserve); + void Statistics(int* Fetches, int* Marks, int* Reads, int* Writes); + void Counts(int* Insert, int* Update, int* Delete, + int* ReadIdx, int* ReadSeq); + void Users(std::vector& users); + int Dialect() { return mDialect; } + + void Create(int dialect); + void Connect(); + bool Connected() { return mHandle == 0 ? false : true; } + void Inactivate(); + void Disconnect(); + void Drop(); + + IBPP::IDatabase* AddRef(); + void Release(); +}; + +class TransactionImpl : public IBPP::ITransaction +{ + // (((((((( OBJECT INTERNALS )))))))) + +private: + int mRefCount; // Reference counter + isc_tr_handle mHandle; // Transaction InterBase + + std::vector mDatabases; // Tableau de IDatabase* + std::vector mStatements; // Tableau de IStatement* + std::vector mBlobs; // Tableau de IBlob* + std::vector mArrays; // Tableau de Array* + std::vector mTPBs; // Tableau de TPB + + void Init(); // A usage exclusif des constructeurs + +public: + isc_tr_handle* GetHandlePtr() { return &mHandle; } + isc_tr_handle GetHandle() { return mHandle; } + + void AttachStatementImpl(StatementImpl*); + void DetachStatementImpl(StatementImpl*); + void AttachBlobImpl(BlobImpl*); + void DetachBlobImpl(BlobImpl*); + void AttachArrayImpl(ArrayImpl*); + void DetachArrayImpl(ArrayImpl*); + void AttachDatabaseImpl(DatabaseImpl* dbi, IBPP::TAM am = IBPP::amWrite, + IBPP::TIL il = IBPP::ilConcurrency, + IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0)); + void DetachDatabaseImpl(DatabaseImpl* dbi); + + TransactionImpl(DatabaseImpl* db, IBPP::TAM am = IBPP::amWrite, + IBPP::TIL il = IBPP::ilConcurrency, + IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0)); + ~TransactionImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + void AttachDatabase(IBPP::Database db, IBPP::TAM am = IBPP::amWrite, + IBPP::TIL il = IBPP::ilConcurrency, + IBPP::TLR lr = IBPP::lrWait, IBPP::TFF flags = IBPP::TFF(0)); + void DetachDatabase(IBPP::Database db); + void AddReservation(IBPP::Database db, + const std::string& table, IBPP::TTR tr); + + void Start(); + bool Started() { return mHandle == 0 ? false : true; } + void Commit(); + void Rollback(); + void CommitRetain(); + void RollbackRetain(); + + IBPP::ITransaction* AddRef(); + void Release(); +}; + +class RowImpl : public IBPP::IRow +{ + // (((((((( OBJECT INTERNALS )))))))) + +private: + int mRefCount; // Reference counter + + XSQLDA* mDescrArea; // XSQLDA descriptor itself + std::vector mNumerics; // Temporary storage for Numerics + std::vector mFloats; // Temporary storage for Floats + std::vector mInt64s; // Temporary storage for 64 bits + std::vector mInt32s; // Temporary storage for 32 bits + std::vector mInt16s; // Temporary storage for 16 bits + std::vector mBools; // Temporary storage for Bools + std::vector mStrings; // Temporary storage for Strings + std::vector mUpdated; // Which columns where updated (Set()) ? + + int mDialect; // Related database dialect + DatabaseImpl* mDatabase; // Related Database (important for Blobs, ...) + TransactionImpl* mTransaction; // Related Transaction (same remark) + + void SetValue(int, IITYPE, const void* value, int = 0); + void* GetValue(int, IITYPE, void* = 0); + +public: + void Free(); + short AllocatedSize() { return mDescrArea->sqln; } + void Resize(int n); + void AllocVariables(); + bool MissingValues(); // Returns wether one of the mMissing[] is true + XSQLDA* Self() { return mDescrArea; } + + RowImpl& operator=(const RowImpl& copied); + RowImpl(const RowImpl& copied); + RowImpl(int dialect, int size, DatabaseImpl* db, TransactionImpl* tr); + ~RowImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + void SetNull(int); + void Set(int, bool); + void Set(int, const char*); // c-strings + void Set(int, const void*, int); // byte buffers + void Set(int, const std::string&); + void Set(int, int16_t); + void Set(int, int32_t); + void Set(int, int64_t); + void Set(int, float); + void Set(int, double); + void Set(int, const IBPP::Timestamp&); + void Set(int, const IBPP::Date&); + void Set(int, const IBPP::Time&); + void Set(int, const IBPP::DBKey&); + void Set(int, const IBPP::Blob&); + void Set(int, const IBPP::Array&); + + bool IsNull(int); + bool Get(int, bool&); + bool Get(int, char*); // c-strings, len unchecked + bool Get(int, void*, int&); // byte buffers + bool Get(int, std::string&); + bool Get(int, int16_t&); + bool Get(int, int32_t&); + bool Get(int, int64_t&); + bool Get(int, float&); + bool Get(int, double&); + bool Get(int, IBPP::Timestamp&); + bool Get(int, IBPP::Date&); + bool Get(int, IBPP::Time&); + bool Get(int, IBPP::DBKey&); + bool Get(int, IBPP::Blob&); + bool Get(int, IBPP::Array&); + + bool IsNull(const std::string&); + bool Get(const std::string&, bool&); + bool Get(const std::string&, char*); // c-strings, len unchecked + bool Get(const std::string&, void*, int&); // byte buffers + bool Get(const std::string&, std::string&); + bool Get(const std::string&, int16_t&); + bool Get(const std::string&, int32_t&); + bool Get(const std::string&, int64_t&); + bool Get(const std::string&, float&); + bool Get(const std::string&, double&); + bool Get(const std::string&, IBPP::Timestamp&); + bool Get(const std::string&, IBPP::Date&); + bool Get(const std::string&, IBPP::Time&); + bool Get(const std::string&, IBPP::DBKey&); + bool Get(const std::string&, IBPP::Blob&); + bool Get(const std::string&, IBPP::Array&); + + int ColumnNum(const std::string&); + const char* ColumnName(int); + const char* ColumnAlias(int); + const char* ColumnTable(int); + IBPP::SDT ColumnType(int); + int ColumnSubtype(int); + int ColumnSize(int); + int ColumnScale(int); + int Columns(); + + bool ColumnUpdated(int); + bool Updated(); + + IBPP::Database DatabasePtr() const; + IBPP::Transaction TransactionPtr() const; + + IBPP::IRow* Clone(); + IBPP::IRow* AddRef(); + void Release(); +}; + +class StatementImpl : public IBPP::IStatement +{ + // (((((((( OBJECT INTERNALS )))))))) + +private: + friend class TransactionImpl; + + int mRefCount; // Reference counter + isc_stmt_handle mHandle; // Statement Handle + + DatabaseImpl* mDatabase; // Attached database + TransactionImpl* mTransaction; // Attached transaction + RowImpl* mInRow; + //bool* mInMissing; // Quels paramètres n'ont pas été spécifiés + RowImpl* mOutRow; + bool mResultSetAvailable; // Executed and result set is available + bool mCursorOpened; // dsql_set_cursor_name was called + IBPP::STT mType; // Type de requète + std::string mSql; // Last SQL statement prepared or executed + + // Internal Methods + void CursorFree(); + +public: + // Properties and Attributes Access Methods + isc_stmt_handle GetHandle() { return mHandle; } + + void AttachDatabaseImpl(DatabaseImpl*); + void DetachDatabaseImpl(); + void AttachTransactionImpl(TransactionImpl*); + void DetachTransactionImpl(); + + StatementImpl(DatabaseImpl*, TransactionImpl*, const std::string&); + ~StatementImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + void Prepare(const std::string& sql); + void Execute(const std::string& sql); + inline void Execute() { Execute(std::string()); } + void ExecuteImmediate(const std::string&); + void CursorExecute(const std::string& cursor, const std::string& sql); + inline void CursorExecute(const std::string& cursor) { CursorExecute(cursor, std::string()); } + bool Fetch(); + bool Fetch(IBPP::Row&); + int AffectedRows(); + void Close(); // Free resources, attachments maintained + std::string& Sql() { return mSql; } + IBPP::STT Type() { return mType; } + + void SetNull(int); + void Set(int, bool); + void Set(int, const char*); // c-strings + void Set(int, const void*, int); // byte buffers + void Set(int, const std::string&); + void Set(int, int16_t); + void Set(int, int32_t); + void Set(int, int64_t); + void Set(int, float); + void Set(int, double); + void Set(int, const IBPP::Timestamp&); + void Set(int, const IBPP::Date&); + void Set(int, const IBPP::Time&); + void Set(int, const IBPP::DBKey&); + void Set(int, const IBPP::Blob&); + void Set(int, const IBPP::Array&); + + bool IsNull(int); + bool Get(int, bool*); + bool Get(int, bool&); + bool Get(int, char*); // c-strings, len unchecked + bool Get(int, void*, int&); // byte buffers + bool Get(int, std::string&); + bool Get(int, int16_t*); + bool Get(int, int16_t&); + bool Get(int, int32_t*); + bool Get(int, int32_t&); + bool Get(int, int64_t*); + bool Get(int, int64_t&); + bool Get(int, float*); + bool Get(int, float&); + bool Get(int, double*); + bool Get(int, double&); + bool Get(int, IBPP::Timestamp&); + bool Get(int, IBPP::Date&); + bool Get(int, IBPP::Time&); + bool Get(int, IBPP::DBKey&); + bool Get(int, IBPP::Blob&); + bool Get(int, IBPP::Array&); + + bool IsNull(const std::string&); + bool Get(const std::string&, bool*); + bool Get(const std::string&, bool&); + bool Get(const std::string&, char*); // c-strings, len unchecked + bool Get(const std::string&, void*, int&); // byte buffers + bool Get(const std::string&, std::string&); + bool Get(const std::string&, int16_t*); + bool Get(const std::string&, int16_t&); + bool Get(const std::string&, int32_t*); + bool Get(const std::string&, int32_t&); + bool Get(const std::string&, int64_t*); + bool Get(const std::string&, int64_t&); + bool Get(const std::string&, float*); + bool Get(const std::string&, float&); + bool Get(const std::string&, double*); + bool Get(const std::string&, double&); + bool Get(const std::string&, IBPP::Timestamp&); + bool Get(const std::string&, IBPP::Date&); + bool Get(const std::string&, IBPP::Time&); + bool Get(const std::string&, IBPP::DBKey&); + bool Get(const std::string&, IBPP::Blob&); + bool Get(const std::string&, IBPP::Array&); + + int ColumnNum(const std::string&); + int ColumnNumAlias(const std::string&); + const char* ColumnName(int); + const char* ColumnAlias(int); + const char* ColumnTable(int); + IBPP::SDT ColumnType(int); + int ColumnSubtype(int); + int ColumnSize(int); + int ColumnScale(int); + int Columns(); + + IBPP::SDT ParameterType(int); + int ParameterSubtype(int); + int ParameterSize(int); + int ParameterScale(int); + int Parameters(); + + void Plan(std::string&); + + IBPP::Database DatabasePtr() const; + IBPP::Transaction TransactionPtr() const; + + IBPP::IStatement* AddRef(); + void Release(); +}; + +class BlobImpl : public IBPP::IBlob +{ + // (((((((( OBJECT INTERNALS )))))))) + +private: + friend class RowImpl; + + int mRefCount; + bool mIdAssigned; + ISC_QUAD mId; + isc_blob_handle mHandle; + bool mWriteMode; + DatabaseImpl* mDatabase; // Belongs to this database + TransactionImpl* mTransaction; // Belongs to this transaction + + void Init(); + void SetId(ISC_QUAD*); + void GetId(ISC_QUAD*); + +public: + void AttachDatabaseImpl(DatabaseImpl*); + void DetachDatabaseImpl(); + void AttachTransactionImpl(TransactionImpl*); + void DetachTransactionImpl(); + + BlobImpl(const BlobImpl&); + BlobImpl(DatabaseImpl*, TransactionImpl* = 0); + ~BlobImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + void Create(); + void Open(); + void Close(); + void Cancel(); + int Read(void*, int size); + void Write(const void*, int size); + void Info(int* Size, int* Largest, int* Segments); + + void Save(const std::string& data); + void Load(std::string& data); + + IBPP::Database DatabasePtr() const; + IBPP::Transaction TransactionPtr() const; + + IBPP::IBlob* AddRef(); + void Release(); +}; + +class ArrayImpl : public IBPP::IArray +{ + // (((((((( OBJECT INTERNALS )))))))) + +private: + friend class RowImpl; + + int mRefCount; // Reference counter + bool mIdAssigned; + ISC_QUAD mId; + bool mDescribed; + ISC_ARRAY_DESC mDesc; + DatabaseImpl* mDatabase; // Database attachée + TransactionImpl* mTransaction; // Transaction attachée + void* mBuffer; // Buffer for native data + int mBufferSize; // Size of this buffer in bytes + int mElemCount; // Count of elements in this array + int mElemSize; // Size of an element in the buffer + + void Init(); + void SetId(ISC_QUAD*); + void GetId(ISC_QUAD*); + void ResetId(); + void AllocArrayBuffer(); + +public: + void AttachDatabaseImpl(DatabaseImpl*); + void DetachDatabaseImpl(); + void AttachTransactionImpl(TransactionImpl*); + void DetachTransactionImpl(); + + ArrayImpl(const ArrayImpl&); + ArrayImpl(DatabaseImpl*, TransactionImpl* = 0); + ~ArrayImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + void Describe(const std::string& table, const std::string& column); + void ReadTo(IBPP::ADT, void*, int); + void WriteFrom(IBPP::ADT, const void*, int); + IBPP::SDT ElementType(); + int ElementSize(); + int ElementScale(); + int Dimensions(); + void Bounds(int dim, int* low, int* high); + void SetBounds(int dim, int low, int high); + + IBPP::Database DatabasePtr() const; + IBPP::Transaction TransactionPtr() const; + + IBPP::IArray* AddRef(); + void Release(); +}; + +// +// EventBufferIterator: used in EventsImpl implementation. +// + +template +struct EventBufferIterator +{ + It mIt; + +public: + EventBufferIterator& operator++() + { mIt += 1 + static_cast(*mIt) + 4; return *this; } + + bool operator == (const EventBufferIterator& i) const { return i.mIt == mIt; } + bool operator != (const EventBufferIterator& i) const { return i.mIt != mIt; } + +#ifdef __BCPLUSPLUS__ +#pragma warn -8027 +#endif + std::string get_name() const + { + return std::string(mIt + 1, mIt + 1 + static_cast(*mIt)); + } +#ifdef __BCPLUSPLUS__ +#pragma warn .8027 +#endif + + uint32_t get_count() const + { + return (*gds.Call()->m_vax_integer) + (const_cast(&*(mIt + 1 + static_cast(*mIt))), 4); + } + + // Those container like begin() and end() allow access to the underlying type + It begin() { return mIt; } + It end() { return mIt + 1 + static_cast(*mIt) + 4; } + + EventBufferIterator() {} + EventBufferIterator(It it) : mIt(it) {} +}; + +class EventsImpl : public IBPP::IEvents +{ + static const size_t MAXEVENTNAMELEN; + static void EventHandler(const char*, short, const char*); + + typedef std::vector ObjRefs; + ObjRefs mObjectReferences; + + typedef std::vector Buffer; + Buffer mEventBuffer; + Buffer mResultsBuffer; + + int mRefCount; // Reference counter + + DatabaseImpl* mDatabase; + ISC_LONG mId; // Firebird internal Id of these events + bool mQueued; // Has isc_que_events() been called? + bool mTrapped; // EventHandled() was called since last que_events() + + void FireActions(); + void Queue(); + void Cancel(); + + EventsImpl& operator=(const EventsImpl&); + EventsImpl(const EventsImpl&); + +public: + void AttachDatabaseImpl(DatabaseImpl*); + void DetachDatabaseImpl(); + + EventsImpl(DatabaseImpl* dbi); + ~EventsImpl(); + + // (((((((( OBJECT INTERFACE )))))))) + +public: + void Add(const std::string&, IBPP::EventInterface*); + void Drop(const std::string&); + void List(std::vector&); + void Clear(); // Drop all events + void Dispatch(); // Dispatch NON async events + + IBPP::Database DatabasePtr() const; + + IBPP::IEvents* AddRef(); + void Release(); +}; + +void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt); +void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt); + +void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm); +void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm); + +void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts); +void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts); + +struct consts // See _ibpp.cpp for initializations of these constants +{ + static const double dscales[19]; + static const int Dec31_1899; + static const int16_t min16; + static const int16_t max16; + static const int32_t min32; + static const int32_t max32; +}; + +} // namespace ibpp_internal + +#endif // __INTERNAL_IBPP_H__ + +// +// Eof +// diff --git a/libs/ibpp/_ibs.cpp b/libs/ibpp/_ibs.cpp new file mode 100644 index 00000000..25e66bc9 --- /dev/null +++ b/libs/ibpp/_ibs.cpp @@ -0,0 +1,109 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: _ibs.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $ +// Subject : IBPP, internal Status class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +int IBS::SqlCode() const +{ + return (int)(*gds.Call()->m_sqlcode)(&mVector[0]); +} + +const char* IBS::ErrorMessage() const +{ + char msg[1024]; + ISC_LONG sqlcode; + + if (! mMessage.empty()) return mMessage.c_str(); // If message compiled, returns it + + // Compiles the message (SQL part) + std::ostringstream message; + sqlcode = (*gds.Call()->m_sqlcode)(mVector); + if (sqlcode != -999) + { + (*gds.Call()->m_sql_interprete)((short)sqlcode, msg, sizeof(msg)); + message<< _("SQL Message : ")<< sqlcode<< "\n"<< msg<< "\n\n"; + } + + message<< _("Engine Code : ")<< EngineCode()<< "\n"; + + // Compiles the message (Engine part) + ISC_STATUS* error = &mVector[0]; + try { (*gds.Call()->m_interprete)(msg, &error); } + catch(...) { msg[0] = '\0'; } + message<< _("Engine Message :")<< "\n"<< msg; + try + { + while ((*gds.Call()->m_interprete)(msg, &error)) + message<< "\n"<< msg; + } + catch (...) { } + + message<< "\n"; + mMessage = message.str(); + return mMessage.c_str(); +} + +void IBS::Reset() +{ + for (int i = 0; i < 20; i++) mVector[i] = 0; + mMessage.erase(); +} + +IBS::IBS() +{ + Reset(); +} + +IBS::~IBS() +{ +} + +/** Copy Constructor +*/ + +IBS::IBS(IBS& copied) +{ + memcpy(mVector, copied.mVector, sizeof(mVector)); +} + +// +// EOF +// diff --git a/libs/ibpp/_rb.cpp b/libs/ibpp/_rb.cpp new file mode 100644 index 00000000..d3dfbc8e --- /dev/null +++ b/libs/ibpp/_rb.cpp @@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: _rb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $ +// Subject : IBPP, internal RB class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * RB == Result Block/Buffer, see Interbase 6.0 C-API +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +char* RB::FindToken(char token) +{ + char* p = mBuffer; + + while (*p != isc_info_end) + { + int len; + + if (*p == token) return p; + len = (*gds.Call()->m_vax_integer)(p+1, 2); + p += (len + 3); + } + + return 0; +} + +char* RB::FindToken(char token, char subtoken) +{ + char* p = mBuffer; + + while (*p != isc_info_end) + { + int len; + + if (*p == token) + { + // Found token, now find subtoken + int inlen = (*gds.Call()->m_vax_integer)(p+1, 2); + p += 3; + while (inlen > 0) + { + if (*p == subtoken) return p; + len = (*gds.Call()->m_vax_integer)(p+1, 2); + p += (len + 3); + inlen -= (len + 3); + } + return 0; + } + len = (*gds.Call()->m_vax_integer)(p+1, 2); + p += (len + 3); + } + + return 0; +} + +int RB::GetValue(char token) +{ + int value; + int len; + char* p = FindToken(token); + + if (p == 0) + throw LogicExceptionImpl("RB::GetValue", _("Token not found.")); + + len = (*gds.Call()->m_vax_integer)(p+1, 2); + if (len == 0) value = 0; + else value = (*gds.Call()->m_vax_integer)(p+3, (short)len); + + return value; +} + +int RB::GetCountValue(char token) +{ + // Specifically used on tokens like isc_info_insert_count and the like + // which return detailed counts per relation. We sum up the values. + int value; + int len; + char* p = FindToken(token); + + if (p == 0) + throw LogicExceptionImpl("RB::GetCountValue", _("Token not found.")); + + // len is the number of bytes in the following array + len = (*gds.Call()->m_vax_integer)(p+1, 2); + p += 3; + value = 0; + while (len > 0) + { + // Each array item is 6 bytes : 2 bytes for the relation_id which + // we skip, and 4 bytes for the count value which we sum up accross + // all tables. + value += (*gds.Call()->m_vax_integer)(p+2, 4); + p += 6; + len -= 6; + } + + return value; +} + +int RB::GetValue(char token, char subtoken) +{ + int value; + int len; + char* p = FindToken(token, subtoken); + + if (p == 0) + throw LogicExceptionImpl("RB::GetValue", _("Token/Subtoken not found.")); + + len = (*gds.Call()->m_vax_integer)(p+1, 2); + if (len == 0) value = 0; + else value = (*gds.Call()->m_vax_integer)(p+3, (short)len); + + return value; +} + +bool RB::GetBool(char token) +{ + int value; + char* p = FindToken(token); + + if (p == 0) + throw LogicExceptionImpl("RB::GetBool", _("Token not found.")); + + value = (*gds.Call()->m_vax_integer)(p+1, 4); + + return value == 0 ? false : true; +} + +int RB::GetString(char token, std::string& data) +{ + int len; + char* p = FindToken(token); + + if (p == 0) + throw LogicExceptionImpl("RB::GetString", _("Token not found.")); + + len = (*gds.Call()->m_vax_integer)(p+1, 2); + data = std::string(p+3, len); + return len; +} + +void RB::Reset() +{ + delete [] mBuffer; + mBuffer = new char [mSize]; + memset(mBuffer, 255, mSize); +} + +RB::RB() +{ + mSize = 1024; + mBuffer = new char [1024]; + memset(mBuffer, 255, mSize); +} + +RB::RB(int Size) +{ + mSize = Size; + mBuffer = new char [Size]; + memset(mBuffer, 255, mSize); +} + +RB::~RB() +{ + try { delete [] mBuffer; } + catch (...) { } +} + +// +// EOF +// diff --git a/libs/ibpp/_spb.cpp b/libs/ibpp/_spb.cpp new file mode 100644 index 00000000..632a0209 --- /dev/null +++ b/libs/ibpp/_spb.cpp @@ -0,0 +1,135 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: _spb.cpp,v 1.2 2009/03/19 20:00:27 faust Exp $ +// Subject : IBPP, internal SPB class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * SPB == Service Parameter Block/Buffer, see Interbase 6.0 C-API +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +const int SPB::BUFFERINCR = 128; + +void SPB::Grow(int needed) +{ + if ((mSize + needed) > mAlloc) + { + // We need to grow the buffer. We use increments of BUFFERINCR bytes. + needed = (needed / BUFFERINCR + 1) * BUFFERINCR; + char* newbuffer = new char[mAlloc + needed]; + if (mBuffer != 0) + { + // Move the old buffer content to the new one + memcpy(newbuffer, mBuffer, mSize); + delete [] mBuffer; + } + mBuffer = newbuffer; + mAlloc += needed; + } +} + +void SPB::Insert(char opcode) +{ + Grow(1); + mBuffer[mSize++] = opcode; +} + +void SPB::InsertString(char type, int lenwidth, const char* data) +{ + int16_t len = (int16_t)strlen(data); + + Grow(1 + lenwidth + len); + mBuffer[mSize++] = type; + switch (lenwidth) + { + case 1 : mBuffer[mSize] = char(len); mSize++; break; + case 2 : *(int16_t*)&mBuffer[mSize] = int16_t((*gds.Call()->m_vax_integer)((char*)&len, 2)); + mSize += 2; break; + default : throw LogicExceptionImpl("IISPB::IISPB", _("Invalid length parameter")); + } + strncpy(&mBuffer[mSize], data, len); + mSize += len; +} + +void SPB::InsertByte(char type, char data) +{ + Grow(1 + 1); + mBuffer[mSize++] = type; + mBuffer[mSize++] = data; +} + +void SPB::InsertQuad(char type, int32_t data) +{ + Grow(1 + 4); + mBuffer[mSize++] = type; + *(int32_t*)&mBuffer[mSize] = int32_t((*gds.Call()->m_vax_integer)((char*)&data, 4)); + mSize += 4; +} + +void SPB::Reset() +{ + if (mBuffer != 0) + { + delete [] mBuffer; + mBuffer = 0; + mSize = 0; + mAlloc = 0; + } +} + +/* +void SPB::Insert(char type, short data) +{ + Grow(1 + 3); + mBuffer[mSize++] = type; + mBuffer[mSize++] = char(2); + *(short*)&mBuffer[mSize] = data; + mSize += 2; +} + +void SPB::Insert(char type, bool data) +{ + Grow(1 + 2); + mBuffer[mSize++] = type; + mBuffer[mSize++] = char(1); + mBuffer[mSize++] = char(data ? 1 : 0); +} +*/ + +// +// EOF +// diff --git a/libs/ibpp/_tpb.cpp b/libs/ibpp/_tpb.cpp new file mode 100644 index 00000000..d27c2d55 --- /dev/null +++ b/libs/ibpp/_tpb.cpp @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: _tpb.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $ +// Subject : IBPP, internal TPB class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * TPB == Transaction Parameter Block/Buffer, see Interbase 6.0 C-API +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +const int TPB::BUFFERINCR = 128; + +void TPB::Grow(int needed) +{ + if (mBuffer == 0) ++needed; // Initial alloc will require one more byte + if ((mSize + needed) > mAlloc) + { + // We need to grow the buffer. We use increments of BUFFERINCR bytes. + needed = (needed / BUFFERINCR + 1) * BUFFERINCR; + char* newbuffer = new char[mAlloc + needed]; + if (mBuffer == 0) + { + // Initial allocation, initialize the version tag + newbuffer[0] = isc_tpb_version3; + mSize = 1; + } + else + { + // Move the old buffer content to the new one + memcpy(newbuffer, mBuffer, mSize); + delete [] mBuffer; + } + mBuffer = newbuffer; + mAlloc += needed; + } +} + +void TPB::Insert(char item) +{ + Grow(1); + mBuffer[mSize++] = item; +} + +void TPB::Insert(const std::string& data) +{ + int len = (int)data.length(); + Grow(1 + len); + mBuffer[mSize++] = (char)len; + strncpy(&mBuffer[mSize], data.c_str(), len); + mSize += len; +} + +void TPB::Reset() +{ + if (mSize != 0) + { + delete [] mBuffer; + mBuffer = 0; + mSize = 0; + mAlloc = 0; + } +} + +// +// EOF +// diff --git a/libs/ibpp/all_in_one.cpp b/libs/ibpp/all_in_one.cpp new file mode 100644 index 00000000..9f74f7e0 --- /dev/null +++ b/libs/ibpp/all_in_one.cpp @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: all_in_one.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $ +// Subject : "All In One" source code file +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// * This file is just an "all in one" holder for all the core source files +// of IBPP. When you build a project made of each individual source code +// files, please DON'T include this one. +// Though if you prefer, maybe for better compiler optimizations, you can +// compile all of IBPP at once by just compiling this single .cpp file, +// which in turn, includes all the others. Presenting such a single +// compilation unit to the compiler may help it do better optimizations. +// This is just provided for convenience and is in no case required. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "_ibpp.cpp" +#include "_dpb.cpp" +#include "_ibs.cpp" +#include "_rb.cpp" +#include "_spb.cpp" +#include "_tpb.cpp" + +#include "array.cpp" +#include "blob.cpp" +#include "database.cpp" +#include "date.cpp" +#include "dbkey.cpp" +#include "events.cpp" +#include "exception.cpp" +#include "row.cpp" +#include "service.cpp" +#include "statement.cpp" +#include "time.cpp" +#include "transaction.cpp" +#include "user.cpp" + +// Eof diff --git a/libs/ibpp/array.cpp b/libs/ibpp/array.cpp new file mode 100644 index 00000000..2dc7ab27 --- /dev/null +++ b/libs/ibpp/array.cpp @@ -0,0 +1,1046 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: array.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $ +// Subject : IBPP, Array class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include +#include + +using namespace ibpp_internals; + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void ArrayImpl::Describe(const std::string& table, const std::string& column) +{ + //if (mIdAssigned) + // throw LogicExceptionImpl("Array::Lookup", _("Array already in use.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Array::Lookup", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Array::Lookup", _("No Transaction is attached.")); + + ResetId(); // Re-use this array object if was previously assigned + + IBS status; + (*gds.Call()->m_array_lookup_bounds)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), const_cast(table.c_str()), + const_cast(column.c_str()), &mDesc); + if (status.Errors()) + throw SQLExceptionImpl(status, "Array::Lookup", + _("isc_array_lookup_bounds failed.")); + + AllocArrayBuffer(); + + mDescribed = true; +} + +void ArrayImpl::SetBounds(int dim, int low, int high) +{ + if (! mDescribed) + throw LogicExceptionImpl("Array::SetBounds", _("Array description not set.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Array::SetBounds", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Array::SetBounds", _("No Transaction is attached.")); + if (dim < 0 || dim > mDesc.array_desc_dimensions-1) + throw LogicExceptionImpl("Array::SetBounds", _("Invalid dimension.")); + if (low > high || + low < mDesc.array_desc_bounds[dim].array_bound_lower || + low > mDesc.array_desc_bounds[dim].array_bound_upper || + high > mDesc.array_desc_bounds[dim].array_bound_upper || + high < mDesc.array_desc_bounds[dim].array_bound_lower) + throw LogicExceptionImpl("Array::SetBounds", + _("Invalid bounds. You can only narrow the bounds.")); + + mDesc.array_desc_bounds[dim].array_bound_lower = short(low); + mDesc.array_desc_bounds[dim].array_bound_upper = short(high); + + AllocArrayBuffer(); +} + +IBPP::SDT ArrayImpl::ElementType() +{ + if (! mDescribed) + throw LogicExceptionImpl("Array::ElementType", + _("Array description not set.")); + + IBPP::SDT value; + switch (mDesc.array_desc_dtype) + { + case blr_text : value = IBPP::sdString; break; + case blr_varying : value = IBPP::sdString; break; + case blr_cstring : value = IBPP::sdString; break; + case blr_short : value = IBPP::sdSmallint; break; + case blr_long : value = IBPP::sdInteger; break; + case blr_int64 : value = IBPP::sdLargeint; break; + case blr_float : value = IBPP::sdFloat; break; + case blr_double : value = IBPP::sdDouble; break; + case blr_timestamp : value = IBPP::sdTimestamp; break; + case blr_sql_date : value = IBPP::sdDate; break; + case blr_sql_time : value = IBPP::sdTime; break; + default : throw LogicExceptionImpl("Array::ElementType", + _("Found an unknown sqltype !")); + } + + return value; +} + +int ArrayImpl::ElementSize() +{ + if (! mDescribed) + throw LogicExceptionImpl("Array::ElementSize", + _("Array description not set.")); + + return mDesc.array_desc_length; +} + +int ArrayImpl::ElementScale() +{ + if (! mDescribed) + throw LogicExceptionImpl("Array::ElementScale", + _("Array description not set.")); + + return mDesc.array_desc_scale; +} + +int ArrayImpl::Dimensions() +{ + if (! mDescribed) + throw LogicExceptionImpl("Array::Dimensions", + _("Array description not set.")); + + return mDesc.array_desc_dimensions; +} + +void ArrayImpl::Bounds(int dim, int* low, int* high) +{ + if (! mDescribed) + throw LogicExceptionImpl("Array::Bounds", _("Array description not set.")); + if (dim < 0 || dim > mDesc.array_desc_dimensions-1) + throw LogicExceptionImpl("Array::Bounds", _("Invalid dimension.")); + if (low == 0 || high == 0) + throw LogicExceptionImpl("Array::Bounds", _("Null reference detected.")); + + *low = mDesc.array_desc_bounds[dim].array_bound_lower; + *high = mDesc.array_desc_bounds[dim].array_bound_upper; +} + +/* + +COMMENTS + +1) +For an array column of type CHAR(X), the internal type returned or expected is blr_text. +In such case, the byte array received or submitted to get/put_slice is formatted in +elements of X bytes, which correspond to what is reported in array_desc_length. +The elements are not '\0' terminated but are right-padded with spaces ' '. + +2) +For an array column of type VARCHAR(X), the internal type is blr_varying. +The underlying format is rather curious and different than what is used in XSQLDA. +The element size is reported in array_desc_length as X. +Yet each element of the byte array is expected to be of size X+2 (just as if we were +to stuff a short in the first 2 bytes to store the length (as is done with XSQLDA). +No. The string of X characters maximum has to be stored in the chunks of X+2 bytes as +a zero-terminated c-string. Note that the buffer is indeed one byte too large. +Internally, the API probably convert in-place in these chunks the zero-terminated string +to a variable-size string with a short in front and the string data non zero-terminated +behind. + +3) +With Interbase 6.0 and Firebird 1.0 (initial april 2002 release), the int64 support is +broken regarding the arrays. It is not possible to work on arrays using a datatype stored +in an int64, as for instance any NUMERIC(x,0) where x is equal or greater than 10. That's +a bug in the engine, not in IBPP, which has been fixed in june 2002. Engines compiled from +the current Firebird CVS code as of july 2002 are okay. As will be the 1.01 Firebird version. +We have no idea if this is fixed or not in Interbase 6.5 though. + +*/ + +void ArrayImpl::ReadTo(IBPP::ADT adtype, void* data, int datacount) +{ + if (! mIdAssigned) + throw LogicExceptionImpl("Array::ReadTo", _("Array Id not read from column.")); + if (! mDescribed) + throw LogicExceptionImpl("Array::ReadTo", _("Array description not set.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Array::ReadTo", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Array::ReadTo", _("No Transaction is attached.")); + if (datacount != mElemCount) + throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements")); + + IBS status; + ISC_LONG lenbuf = mBufferSize; + (*gds.Call()->m_array_get_slice)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf); + if (status.Errors()) + throw SQLExceptionImpl(status, "Array::ReadTo", _("isc_array_get_slice failed.")); + if (lenbuf != mBufferSize) + throw SQLExceptionImpl(status, "Array::ReadTo", _("Internal buffer size discrepancy.")); + + // Now, convert the types and copy values to the user array... + int len; + char* src = (char*)mBuffer; + char* dst = (char*)data; + + switch (mDesc.array_desc_dtype) + { + case blr_text : + if (adtype == IBPP::adString) + { + for (int i = 0; i < mElemCount; i++) + { + strncpy(dst, src, mElemSize); + dst[mElemSize] = '\0'; + src += mElemSize; + dst += (mElemSize + 1); + } + } + else if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1') + *(bool*)dst = true; + else *(bool*)dst = false; + src += mElemSize; + dst += sizeof(bool); + } + } + else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types.")); + break; + + case blr_varying : + if (adtype == IBPP::adString) + { + for (int i = 0; i < mElemCount; i++) + { + len = (int)strlen(src); + if (len > mElemSize-2) len = mElemSize-2; + strncpy(dst, src, len); + dst[len] = '\0'; + src += mElemSize; + dst += (mElemSize - 2 + 1); + } + } + else if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + if (*src == 't' || *src == 'T' || *src == 'y' || *src == 'Y' || *src == '1') + *(bool*)dst = true; + else *(bool*)dst = false; + src += mElemSize; + dst += sizeof(bool); + } + } + else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types.")); + break; + + case blr_short : + if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *(bool*)dst = (*(short*)src != 0) ? true : false; + src += mElemSize; + dst += sizeof(bool); + } + } + else if (adtype == IBPP::adInt16) + { + for (int i = 0; i < mElemCount; i++) + { + *(short*)dst = *(short*)src; + src += mElemSize; + dst += sizeof(short); + } + } + else if (adtype == IBPP::adInt32) + { + for (int i = 0; i < mElemCount; i++) + { + *(int*)dst = (int)*(short*)src; + src += mElemSize; + dst += sizeof(int); + } + } + else if (adtype == IBPP::adInt64) + { + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = (int64_t)*(short*)src; + src += mElemSize; + dst += sizeof(int64_t); + } + } + else if (adtype == IBPP::adFloat) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(float*)dst = (float)(*(short*)src / divisor); + src += mElemSize; + dst += sizeof(float); + } + } + else if (adtype == IBPP::adDouble) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(double*)dst = (double)(*(short*)src / divisor); + src += mElemSize; + dst += sizeof(double); + } + } + else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types.")); + break; + + case blr_long : + if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *(bool*)dst = (*(long*)src != 0) ? true : false; + src += mElemSize; + dst += sizeof(bool); + } + } + else if (adtype == IBPP::adInt16) + { + for (int i = 0; i < mElemCount; i++) + { + if (*(long*)src < consts::min16 || *(long*)src > consts::max16) + throw LogicExceptionImpl("Array::ReadTo", + _("Out of range numeric conversion !")); + *(short*)dst = short(*(long*)src); + src += mElemSize; + dst += sizeof(short); + } + } + else if (adtype == IBPP::adInt32) + { + for (int i = 0; i < mElemCount; i++) + { + *(long*)dst = *(long*)src; + src += mElemSize; + dst += sizeof(long); + } + } + else if (adtype == IBPP::adInt64) + { + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = (int64_t)*(long*)src; + src += mElemSize; + dst += sizeof(int64_t); + } + } + else if (adtype == IBPP::adFloat) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(float*)dst = (float)(*(long*)src / divisor); + src += mElemSize; + dst += sizeof(float); + } + } + else if (adtype == IBPP::adDouble) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(double*)dst = (double)(*(long*)src / divisor); + src += mElemSize; + dst += sizeof(double); + } + } + else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types.")); + break; + + case blr_int64 : + if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *(bool*)dst = (*(int64_t*)src != 0) ? true : false; + src += mElemSize; + dst += sizeof(bool); + } + } + else if (adtype == IBPP::adInt16) + { + for (int i = 0; i < mElemCount; i++) + { + if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16) + throw LogicExceptionImpl("Array::ReadTo", + _("Out of range numeric conversion !")); + *(short*)dst = short(*(int64_t*)src); + src += mElemSize; + dst += sizeof(short); + } + } + else if (adtype == IBPP::adInt32) + { + for (int i = 0; i < mElemCount; i++) + { + if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32) + throw LogicExceptionImpl("Array::ReadTo", + _("Out of range numeric conversion !")); + *(long*)dst = (long)*(int64_t*)src; + src += mElemSize; + dst += sizeof(long); + } + } + else if (adtype == IBPP::adInt64) + { + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = *(int64_t*)src; + src += mElemSize; + dst += sizeof(int64_t); + } + } + else if (adtype == IBPP::adFloat) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(float*)dst = (float)(*(int64_t*)src / divisor); + src += mElemSize; + dst += sizeof(float); + } + } + else if (adtype == IBPP::adDouble) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(double*)dst = (double)(*(int64_t*)src / divisor); + src += mElemSize; + dst += sizeof(double); + } + } + else throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types.")); + break; + + case blr_float : + if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0) + throw LogicExceptionImpl("Array::ReadTo", _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + *(float*)dst = *(float*)src; + src += mElemSize; + dst += sizeof(float); + } + break; + + case blr_double : + if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::ReadTo", + _("Incompatible types.")); + if (mDesc.array_desc_scale != 0) + { + // Round to scale of NUMERIC(x,y) + double divisor = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(double*)dst = (double)(*(double*)src / divisor); + src += mElemSize; + dst += sizeof(double); + } + } + else + { + for (int i = 0; i < mElemCount; i++) + { + *(double*)dst = *(double*)src; + src += mElemSize; + dst += sizeof(double); + } + } + break; + + case blr_timestamp : + if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo", + _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + decodeTimestamp(*(IBPP::Timestamp*)dst, *(ISC_TIMESTAMP*)src); + src += mElemSize; + dst += sizeof(IBPP::Timestamp); + } + break; + + case blr_sql_date : + if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo", + _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + decodeDate(*(IBPP::Date*)dst, *(ISC_DATE*)src); + src += mElemSize; + dst += sizeof(IBPP::Date); + } + break; + + case blr_sql_time : + if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo", + _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + decodeTime(*(IBPP::Time*)dst, *(ISC_TIME*)src); + src += mElemSize; + dst += sizeof(IBPP::Time); + } + break; + + default : + throw LogicExceptionImpl("Array::ReadTo", _("Unknown sql type.")); + } +} + +void ArrayImpl::WriteFrom(IBPP::ADT adtype, const void* data, int datacount) +{ + if (! mDescribed) + throw LogicExceptionImpl("Array::WriteFrom", _("Array description not set.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Array::WriteFrom", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Array::WriteFrom", _("No Transaction is attached.")); + if (datacount != mElemCount) + throw LogicExceptionImpl("Array::ReadTo", _("Wrong count of array elements")); + + // Read user data and convert types to the mBuffer + int len; + char* src = (char*)data; + char* dst = (char*)mBuffer; + + switch (mDesc.array_desc_dtype) + { + case blr_text : + if (adtype == IBPP::adString) + { + for (int i = 0; i < mElemCount; i++) + { + len = (int)strlen(src); + if (len > mElemSize) len = mElemSize; + strncpy(dst, src, len); + while (len < mElemSize) dst[len++] = ' '; + src += (mElemSize + 1); + dst += mElemSize; + } + } + else if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *dst = *(bool*)src ? 'T' : 'F'; + len = 1; + while (len < mElemSize) dst[len++] = ' '; + src += sizeof(bool); + dst += mElemSize; + } + } + else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types.")); + break; + + case blr_varying : + if (adtype == IBPP::adString) + { + for (int i = 0; i < mElemCount; i++) + { + len = (int)strlen(src); + if (len > mElemSize-2) len = mElemSize-2; + strncpy(dst, src, len); + dst[len] = '\0'; + src += (mElemSize - 2 + 1); + dst += mElemSize; + } + } + else if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *(short*)dst = (short)1; + dst[2] = *(bool*)src ? 'T' : 'F'; + src += sizeof(bool); + dst += mElemSize; + } + } + else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types.")); + break; + + case blr_short : + if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *(short*)dst = short(*(bool*)src ? 1 : 0); + src += sizeof(bool); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt16) + { + for (int i = 0; i < mElemCount; i++) + { + *(short*)dst = *(short*)src; + src += sizeof(short); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt32) + { + for (int i = 0; i < mElemCount; i++) + { + if (*(long*)src < consts::min16 || *(long*)src > consts::max16) + throw LogicExceptionImpl("Array::WriteFrom", + _("Out of range numeric conversion !")); + *(short*)dst = (short)*(int*)src; + src += sizeof(int); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt64) + { + for (int i = 0; i < mElemCount; i++) + { + if (*(int64_t*)src < consts::min16 || *(int64_t*)src > consts::max16) + throw LogicExceptionImpl("Array::WriteFrom", + _("Out of range numeric conversion !")); + *(short*)dst = (short)*(int64_t*)src; + src += sizeof(int64_t); + dst += mElemSize; + } + } + else if (adtype == IBPP::adFloat) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(short*)dst = + (short)floor(*(float*)src * multiplier + 0.5); + src += sizeof(float); + dst += mElemSize; + } + } + else if (adtype == IBPP::adDouble) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(short*)dst = + (short)floor(*(double*)src * multiplier + 0.5); + src += sizeof(double); + dst += mElemSize; + } + } + else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types.")); + break; + + case blr_long : + if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *(long*)dst = *(bool*)src ? 1 : 0; + src += sizeof(bool); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt16) + { + for (int i = 0; i < mElemCount; i++) + { + *(long*)dst = *(short*)src; + src += sizeof(short); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt32) + { + for (int i = 0; i < mElemCount; i++) + { + *(long*)dst = *(long*)src; + src += sizeof(long); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt64) + { + for (int i = 0; i < mElemCount; i++) + { + if (*(int64_t*)src < consts::min32 || *(int64_t*)src > consts::max32) + throw LogicExceptionImpl("Array::WriteFrom", + _("Out of range numeric conversion !")); + *(long*)dst = (long)*(int64_t*)src; + src += sizeof(int64_t); + dst += mElemSize; + } + } + else if (adtype == IBPP::adFloat) + { + // This SQL_INT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(long*)dst = + (long)floor(*(float*)src * multiplier + 0.5); + src += sizeof(float); + dst += mElemSize; + } + } + else if (adtype == IBPP::adDouble) + { + // This SQL_INT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(long*)dst = + (long)floor(*(double*)src * multiplier + 0.5); + src += sizeof(double); + dst += mElemSize; + } + } + else throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types.")); + break; + + case blr_int64 : + if (adtype == IBPP::adBool) + { + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = *(bool*)src ? 1 : 0; + src += sizeof(bool); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt16) + { + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = *(short*)src; + src += sizeof(short); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt32) + { + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = *(long*)src; + src += sizeof(long); + dst += mElemSize; + } + } + else if (adtype == IBPP::adInt64) + { + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = *(int64_t*)src; + src += sizeof(int64_t); + dst += mElemSize; + } + } + else if (adtype == IBPP::adFloat) + { + // This SQL_INT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = + (int64_t)floor(*(float*)src * multiplier + 0.5); + src += sizeof(float); + dst += mElemSize; + } + } + else if (adtype == IBPP::adDouble) + { + // This SQL_INT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(int64_t*)dst = + (int64_t)floor(*(double*)src * multiplier + 0.5); + src += sizeof(double); + dst += mElemSize; + } + } + else + throw LogicExceptionImpl("Array::WriteFrom", + _("Incompatible types (blr_int64 and ADT %d)."), (int)adtype); + break; + + case blr_float : + if (adtype != IBPP::adFloat || mDesc.array_desc_scale != 0) + throw LogicExceptionImpl("Array::WriteFrom", _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + *(float*)dst = *(float*)src; + src += sizeof(float); + dst += mElemSize; + } + break; + + case blr_double : + if (adtype != IBPP::adDouble) throw LogicExceptionImpl("Array::WriteFrom", + _("Incompatible types.")); + if (mDesc.array_desc_scale != 0) + { + // Round to scale of NUMERIC(x,y) + double multiplier = consts::dscales[-mDesc.array_desc_scale]; + for (int i = 0; i < mElemCount; i++) + { + *(double*)dst = + floor(*(double*)src * multiplier + 0.5) / multiplier; + src += sizeof(double); + dst += mElemSize; + } + } + else + { + for (int i = 0; i < mElemCount; i++) + { + *(double*)dst = *(double*)src; + src += sizeof(double); + dst += mElemSize; + } + } + break; + + case blr_timestamp : + if (adtype != IBPP::adTimestamp) throw LogicExceptionImpl("Array::ReadTo", + _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + encodeTimestamp(*(ISC_TIMESTAMP*)dst, *(IBPP::Timestamp*)src); + src += sizeof(IBPP::Timestamp); + dst += mElemSize; + } + break; + + case blr_sql_date : + if (adtype != IBPP::adDate) throw LogicExceptionImpl("Array::ReadTo", + _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + encodeDate(*(ISC_DATE*)dst, *(IBPP::Date*)src); + src += sizeof(IBPP::Date); + dst += mElemSize; + } + break; + + case blr_sql_time : + if (adtype != IBPP::adTime) throw LogicExceptionImpl("Array::ReadTo", + _("Incompatible types.")); + for (int i = 0; i < mElemCount; i++) + { + encodeTime(*(ISC_TIME*)dst, *(IBPP::Time*)src); + src += sizeof(IBPP::Time); + dst += mElemSize; + } + break; + + default : + throw LogicExceptionImpl("Array::WriteFrom", _("Unknown sql type.")); + } + + IBS status; + ISC_LONG lenbuf = mBufferSize; + (*gds.Call()->m_array_put_slice)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), &mId, &mDesc, mBuffer, &lenbuf); + if (status.Errors()) + throw SQLExceptionImpl(status, "Array::WriteFrom", _("isc_array_put_slice failed.")); + if (lenbuf != mBufferSize) + throw SQLExceptionImpl(status, "Array::WriteFrom", _("Internal buffer size discrepancy.")); +} + +IBPP::Database ArrayImpl::DatabasePtr() const +{ + if (mDatabase == 0) throw LogicExceptionImpl("Array::DatabasePtr", + _("No Database is attached.")); + return mDatabase; +} + +IBPP::Transaction ArrayImpl::TransactionPtr() const +{ + if (mTransaction == 0) throw LogicExceptionImpl("Array::TransactionPtr", + _("No Transaction is attached.")); + return mTransaction; +} + +IBPP::IArray* ArrayImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + return this; +} + +void ArrayImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void ArrayImpl::Init() +{ + ResetId(); + mDescribed = false; + mDatabase = 0; + mTransaction = 0; + mBuffer = 0; + mBufferSize = 0; +} + +void ArrayImpl::SetId(ISC_QUAD* quad) +{ + if (quad == 0) + throw LogicExceptionImpl("ArrayImpl::SetId", _("Null Id reference detected.")); + + memcpy(&mId, quad, sizeof(mId)); + mIdAssigned = true; +} + +void ArrayImpl::GetId(ISC_QUAD* quad) +{ + if (quad == 0) + throw LogicExceptionImpl("ArrayImpl::GetId", _("Null Id reference detected.")); + + memcpy(quad, &mId, sizeof(mId)); +} + +void ArrayImpl::ResetId() +{ + memset(&mId, 0, sizeof(mId)); + mIdAssigned = false; +} + +void ArrayImpl::AllocArrayBuffer() +{ + // Clean previous buffer if any + if (mBuffer != 0) delete [] (char*)mBuffer; + mBuffer = 0; + + // Computes total number of elements in the array or slice + mElemCount = 1; + for (int i = 0; i < mDesc.array_desc_dimensions; i++) + { + mElemCount = mElemCount * + (mDesc.array_desc_bounds[i].array_bound_upper - + mDesc.array_desc_bounds[i].array_bound_lower + 1); + } + + // Allocates a buffer for this count of elements + mElemSize = mDesc.array_desc_length; + if (mDesc.array_desc_dtype == blr_varying) mElemSize += 2; + else if (mDesc.array_desc_dtype == blr_cstring) mElemSize += 1; + mBufferSize = mElemSize * mElemCount; + mBuffer = (void*) new char[mBufferSize]; +} + +void ArrayImpl::AttachDatabaseImpl(DatabaseImpl* database) +{ + if (database == 0) throw LogicExceptionImpl("Array::AttachDatabase", + _("Can't attach a 0 Database object.")); + + if (mDatabase != 0) mDatabase->DetachArrayImpl(this); + mDatabase = database; + mDatabase->AttachArrayImpl(this); +} + +void ArrayImpl::AttachTransactionImpl(TransactionImpl* transaction) +{ + if (transaction == 0) throw LogicExceptionImpl("Array::AttachTransaction", + _("Can't attach a 0 Transaction object.")); + + if (mTransaction != 0) mTransaction->DetachArrayImpl(this); + mTransaction = transaction; + mTransaction->AttachArrayImpl(this); +} + +void ArrayImpl::DetachDatabaseImpl() +{ + if (mDatabase == 0) return; + + mDatabase->DetachArrayImpl(this); + mDatabase = 0; +} + +void ArrayImpl::DetachTransactionImpl() +{ + if (mTransaction == 0) return; + + mTransaction->DetachArrayImpl(this); + mTransaction = 0; +} + +ArrayImpl::ArrayImpl(DatabaseImpl* database, TransactionImpl* transaction) + : mRefCount(0) +{ + Init(); + AttachDatabaseImpl(database); + if (transaction != 0) AttachTransactionImpl(transaction); +} + +ArrayImpl::~ArrayImpl() +{ + try { if (mTransaction != 0) mTransaction->DetachArrayImpl(this); } + catch (...) {} + try { if (mDatabase != 0) mDatabase->DetachArrayImpl(this); } + catch (...) {} + try { if (mBuffer != 0) delete [] (char*)mBuffer; } + catch (...) {} +} + +// +// EOF +// diff --git a/libs/ibpp/blob.cpp b/libs/ibpp/blob.cpp new file mode 100644 index 00000000..298fe706 --- /dev/null +++ b/libs/ibpp/blob.cpp @@ -0,0 +1,381 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: blob.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $ +// Subject : IBPP, Blob class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void BlobImpl::Open() +{ + if (mHandle != 0) + throw LogicExceptionImpl("Blob::Open", _("Blob already opened.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Blob::Open", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Blob::Open", _("No Transaction is attached.")); + if (! mIdAssigned) + throw LogicExceptionImpl("Blob::Open", _("Blob Id is not assigned.")); + + IBS status; + (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Open", _("isc_open_blob2 failed.")); + mWriteMode = false; +} + +void BlobImpl::Create() +{ + if (mHandle != 0) + throw LogicExceptionImpl("Blob::Create", _("Blob already opened.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Blob::Create", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Blob::Create", _("No Transaction is attached.")); + + IBS status; + (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Create", + _("isc_create_blob failed.")); + mIdAssigned = true; + mWriteMode = true; +} + +void BlobImpl::Close() +{ + if (mHandle == 0) return; // Not opened anyway + + IBS status; + (*gds.Call()->m_close_blob)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Close", _("isc_close_blob failed.")); + mHandle = 0; +} + +void BlobImpl::Cancel() +{ + if (mHandle == 0) return; // Not opened anyway + + if (! mWriteMode) + throw LogicExceptionImpl("Blob::Cancel", _("Can't cancel a Blob opened for read")); + + IBS status; + (*gds.Call()->m_cancel_blob)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Cancel", _("isc_cancel_blob failed.")); + mHandle = 0; + mIdAssigned = false; +} + +int BlobImpl::Read(void* buffer, int size) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Blob::Read", _("The Blob is not opened")); + if (mWriteMode) + throw LogicExceptionImpl("Blob::Read", _("Can't read from Blob opened for write")); + if (size < 1 || size > (64*1024-1)) + throw LogicExceptionImpl("Blob::Read", _("Invalid segment size (max 64Kb-1)")); + + IBS status; + unsigned short bytesread; + ISC_STATUS result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle, &bytesread, + (unsigned short)size, (char*)buffer); + if (result == isc_segstr_eof) return 0; // Fin du blob + if (result != isc_segment && status.Errors()) + throw SQLExceptionImpl(status, "Blob::Read", _("isc_get_segment failed.")); + return (int)bytesread; +} + +void BlobImpl::Write(const void* buffer, int size) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Blob::Write", _("The Blob is not opened")); + if (! mWriteMode) + throw LogicExceptionImpl("Blob::Write", _("Can't write to Blob opened for read")); + if (size < 1 || size > (64*1024-1)) + throw LogicExceptionImpl("Blob::Write", _("Invalid segment size (max 64Kb-1)")); + + IBS status; + (*gds.Call()->m_put_segment)(status.Self(), &mHandle, + (unsigned short)size, (char*)buffer); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Write", _("isc_put_segment failed.")); +} + +void BlobImpl::Info(int* Size, int* Largest, int* Segments) +{ + char items[] = {isc_info_blob_total_length, + isc_info_blob_max_segment, + isc_info_blob_num_segments}; + + if (mHandle == 0) + throw LogicExceptionImpl("Blob::GetInfo", _("The Blob is not opened")); + + IBS status; + RB result(100); + (*gds.Call()->m_blob_info)(status.Self(), &mHandle, sizeof(items), items, + (short)result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::GetInfo", _("isc_blob_info failed.")); + + if (Size != 0) *Size = result.GetValue(isc_info_blob_total_length); + if (Largest != 0) *Largest = result.GetValue(isc_info_blob_max_segment); + if (Segments != 0) *Segments = result.GetValue(isc_info_blob_num_segments); +} + +void BlobImpl::Save(const std::string& data) +{ + if (mHandle != 0) + throw LogicExceptionImpl("Blob::Save", _("Blob already opened.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Blob::Save", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Blob::Save", _("No Transaction is attached.")); + + IBS status; + (*gds.Call()->m_create_blob2)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Save", + _("isc_create_blob failed.")); + mIdAssigned = true; + mWriteMode = true; + + size_t pos = 0; + size_t len = data.size(); + while (len != 0) + { + size_t blklen = (len < 32*1024-1) ? len : 32*1024-1; + status.Reset(); + (*gds.Call()->m_put_segment)(status.Self(), &mHandle, + (unsigned short)blklen, const_cast(data.data()+pos)); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Save", + _("isc_put_segment failed.")); + pos += blklen; + len -= blklen; + } + + status.Reset(); + (*gds.Call()->m_close_blob)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Save", _("isc_close_blob failed.")); + mHandle = 0; +} + +void BlobImpl::Load(std::string& data) +{ + if (mHandle != 0) + throw LogicExceptionImpl("Blob::Load", _("Blob already opened.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Blob::Load", _("No Database is attached.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Blob::Load", _("No Transaction is attached.")); + if (! mIdAssigned) + throw LogicExceptionImpl("Blob::Load", _("Blob Id is not assigned.")); + + IBS status; + (*gds.Call()->m_open_blob2)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), &mHandle, &mId, 0, 0); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Load", _("isc_open_blob2 failed.")); + mWriteMode = false; + + size_t blklen = 32*1024-1; + data.resize(blklen); + + size_t size = 0; + size_t pos = 0; + for (;;) + { + status.Reset(); + unsigned short bytesread; + ISC_STATUS result = (*gds.Call()->m_get_segment)(status.Self(), &mHandle, + &bytesread, (unsigned short)blklen, + const_cast(data.data()+pos)); + if (result == isc_segstr_eof) break; // End of blob + if (result != isc_segment && status.Errors()) + throw SQLExceptionImpl(status, "Blob::Load", _("isc_get_segment failed.")); + + pos += bytesread; + size += bytesread; + data.resize(size + blklen); + } + data.resize(size); + + status.Reset(); + (*gds.Call()->m_close_blob)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Blob::Load", _("isc_close_blob failed.")); + mHandle = 0; +} + +IBPP::Database BlobImpl::DatabasePtr() const +{ + if (mDatabase == 0) throw LogicExceptionImpl("Blob::DatabasePtr", + _("No Database is attached.")); + return mDatabase; +} + +IBPP::Transaction BlobImpl::TransactionPtr() const +{ + if (mTransaction == 0) throw LogicExceptionImpl("Blob::TransactionPtr", + _("No Transaction is attached.")); + return mTransaction; +} + +IBPP::IBlob* BlobImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + return this; +} + +void BlobImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void BlobImpl::Init() +{ + mIdAssigned = false; + mWriteMode = false; + mHandle = 0; + mDatabase = 0; + mTransaction = 0; +} + +void BlobImpl::SetId(ISC_QUAD* quad) +{ + if (mHandle != 0) + throw LogicExceptionImpl("BlobImpl::SetId", _("Can't set Id on an opened BlobImpl.")); + if (quad == 0) + throw LogicExceptionImpl("BlobImpl::SetId", _("Null Id reference detected.")); + + memcpy(&mId, quad, sizeof(mId)); + mIdAssigned = true; +} + +void BlobImpl::GetId(ISC_QUAD* quad) +{ + if (mHandle != 0) + throw LogicExceptionImpl("BlobImpl::GetId", _("Can't get Id on an opened BlobImpl.")); + if (! mWriteMode) + throw LogicExceptionImpl("BlobImpl::GetId", _("Can only get Id of a newly created Blob.")); + if (quad == 0) + throw LogicExceptionImpl("BlobImpl::GetId", _("Null Id reference detected.")); + + memcpy(quad, &mId, sizeof(mId)); +} + +void BlobImpl::AttachDatabaseImpl(DatabaseImpl* database) +{ + if (database == 0) throw LogicExceptionImpl("Blob::AttachDatabase", + _("Can't attach a NULL Database object.")); + + if (mDatabase != 0) mDatabase->DetachBlobImpl(this); + mDatabase = database; + mDatabase->AttachBlobImpl(this); +} + +void BlobImpl::AttachTransactionImpl(TransactionImpl* transaction) +{ + if (transaction == 0) throw LogicExceptionImpl("Blob::AttachTransaction", + _("Can't attach a NULL Transaction object.")); + + if (mTransaction != 0) mTransaction->DetachBlobImpl(this); + mTransaction = transaction; + mTransaction->AttachBlobImpl(this); +} + +void BlobImpl::DetachDatabaseImpl() +{ + if (mDatabase == 0) return; + + mDatabase->DetachBlobImpl(this); + mDatabase = 0; +} + +void BlobImpl::DetachTransactionImpl() +{ + if (mTransaction == 0) return; + + mTransaction->DetachBlobImpl(this); + mTransaction = 0; +} + +BlobImpl::BlobImpl(DatabaseImpl* database, TransactionImpl* transaction) + : mRefCount(0) +{ + Init(); + AttachDatabaseImpl(database); + if (transaction != 0) AttachTransactionImpl(transaction); +} + +BlobImpl::~BlobImpl() +{ + try + { + if (mHandle != 0) + { + if (mWriteMode) Cancel(); + else Close(); + } + } + catch (...) { } + + try { if (mTransaction != 0) mTransaction->DetachBlobImpl(this); } + catch (...) { } + try { if (mDatabase != 0) mDatabase->DetachBlobImpl(this); } + catch (...) { } +} + +// +// EOF +// diff --git a/libs/ibpp/database.cpp b/libs/ibpp/database.cpp new file mode 100644 index 00000000..64b705d2 --- /dev/null +++ b/libs/ibpp/database.cpp @@ -0,0 +1,483 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: database.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $ +// Subject : IBPP, Database class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void DatabaseImpl::Create(int dialect) +{ + if (mHandle != 0) + throw LogicExceptionImpl("Database::Create", _("Database is already connected.")); + if (mDatabaseName.empty()) + throw LogicExceptionImpl("Database::Create", _("Unspecified database name.")); + if (mUserName.empty()) + throw LogicExceptionImpl("Database::Create", _("Unspecified user name.")); + if (dialect != 1 && dialect != 3) + throw LogicExceptionImpl("Database::Create", _("Only dialects 1 and 3 are supported.")); + + // Build the SQL Create Statement + std::string create; + create.assign("CREATE DATABASE '"); + if (! mServerName.empty()) create.append(mServerName).append(":"); + create.append(mDatabaseName).append("' "); + + create.append("USER '").append(mUserName).append("' "); + if (! mUserPassword.empty()) + create.append("PASSWORD '").append(mUserPassword).append("' "); + + if (! mCreateParams.empty()) create.append(mCreateParams); + + // Call ExecuteImmediate to create the database + isc_tr_handle tr_handle = 0; + IBS status; + (*gds.Call()->m_dsql_execute_immediate)(status.Self(), &mHandle, &tr_handle, + 0, const_cast(create.c_str()), short(dialect), NULL); + if (status.Errors()) + throw SQLExceptionImpl(status, "Database::Create", _("isc_dsql_execute_immediate failed")); + + Disconnect(); +} + +void DatabaseImpl::Connect() +{ + if (mHandle != 0) return; // Already connected + + if (mDatabaseName.empty()) + throw LogicExceptionImpl("Database::Connect", _("Unspecified database name.")); + if (mUserName.empty()) + throw LogicExceptionImpl("Database::Connect", _("Unspecified user name.")); + + // Build a DPB based on the properties + DPB dpb; + dpb.Insert(isc_dpb_user_name, mUserName.c_str()); + dpb.Insert(isc_dpb_password, mUserPassword.c_str()); + if (! mRoleName.empty()) dpb.Insert(isc_dpb_sql_role_name, mRoleName.c_str()); + if (! mCharSet.empty()) dpb.Insert(isc_dpb_lc_ctype, mCharSet.c_str()); + + std::string connect; + if (! mServerName.empty()) + connect.assign(mServerName).append(":"); + connect.append(mDatabaseName); + + IBS status; + (*gds.Call()->m_attach_database)(status.Self(), (short)connect.size(), + const_cast(connect.c_str()), &mHandle, dpb.Size(), dpb.Self()); + if (status.Errors()) + { + mHandle = 0; // Should be, but better be sure... + throw SQLExceptionImpl(status, "Database::Connect", _("isc_attach_database failed")); + } + + // Now, get ODS version information and dialect. + // If ODS major is lower of equal to 9, we reject the connection. + // If ODS major is 10 or higher, this is at least an InterBase 6.x Server + // OR FireBird 1.x Server. + + char items[] = {isc_info_ods_version, + isc_info_db_SQL_dialect, + isc_info_end}; + RB result(100); + + status.Reset(); + (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items, + result.Size(), result.Self()); + if (status.Errors()) + { + status.Reset(); + (*gds.Call()->m_detach_database)(status.Self(), &mHandle); + mHandle = 0; // Should be, but better be sure... + throw SQLExceptionImpl(status, "Database::Connect", _("isc_database_info failed")); + } + + int ODS = result.GetValue(isc_info_ods_version); + if (ODS <= 9) + { + status.Reset(); + (*gds.Call()->m_detach_database)(status.Self(), &mHandle); + mHandle = 0; // Should be, but better be sure... + throw LogicExceptionImpl("Database::Connect", + _("Unsupported Server : wrong ODS version (%d), at least '10' required."), ODS); + } + + mDialect = result.GetValue(isc_info_db_SQL_dialect); + if (mDialect != 1 && mDialect != 3) + { + status.Reset(); + (*gds.Call()->m_detach_database)(status.Self(), &mHandle); + mHandle = 0; // Should be, but better be sure... + throw LogicExceptionImpl("Database::Connect", _("Dialect 1 or 3 required")); + } + + // Now, verify the GDS32.DLL we are using is compatible with the server + if (ODS >= 10 && gds.Call()->mGDSVersion < 60) + { + status.Reset(); + (*gds.Call()->m_detach_database)(status.Self(), &mHandle); + mHandle = 0; // Should be, but better be sure... + throw LogicExceptionImpl("Database::Connect", _("GDS32.DLL version 5 against IBSERVER 6")); + } +} + +void DatabaseImpl::Inactivate() +{ + if (mHandle == 0) return; // Not connected anyway + + IBS status; + + // Rollback any started transaction... + for (unsigned i = 0; i < mTransactions.size(); i++) + { + if (mTransactions[i]->Started()) + mTransactions[i]->Rollback(); + } + + // Cancel all pending event traps + for (unsigned i = 0; i < mEvents.size(); i++) + mEvents[i]->Clear(); + + // Let's detach from all Blobs + while (mBlobs.size() > 0) + mBlobs.back()->DetachDatabaseImpl(); + + // Let's detach from all Arrays + while (mArrays.size() > 0) + mArrays.back()->DetachDatabaseImpl(); + + // Let's detach from all Statements + while (mStatements.size() > 0) + mStatements.back()->DetachDatabaseImpl(); + + // Let's detach from all Transactions + while (mTransactions.size() > 0) + mTransactions.back()->DetachDatabaseImpl(this); + + // Let's detach from all Events + while (mEvents.size() > 0) + mEvents.back()->DetachDatabaseImpl(); +} + +void DatabaseImpl::Disconnect() +{ + if (mHandle == 0) return; // Not connected anyway + + // Put the connection to rest + Inactivate(); + + // Detach from the server + IBS status; + (*gds.Call()->m_detach_database)(status.Self(), &mHandle); + + // Should we throw, set mHandle to 0 first, because Disconnect() may + // be called from Database destructor (keeps the object coherent). + mHandle = 0; + if (status.Errors()) + throw SQLExceptionImpl(status, "Database::Disconnect", _("isc_detach_database failed")); +} + +void DatabaseImpl::Drop() +{ + if (mHandle == 0) + throw LogicExceptionImpl("Database::Drop", _("Database must be connected.")); + + // Put the connection to a rest + Inactivate(); + + IBS vector; + (*gds.Call()->m_drop_database)(vector.Self(), &mHandle); + if (vector.Errors()) + throw SQLExceptionImpl(vector, "Database::Drop", _("isc_drop_database failed")); + + mHandle = 0; +} + +void DatabaseImpl::Info(int* ODSMajor, int* ODSMinor, + int* PageSize, int* Pages, int* Buffers, int* Sweep, + bool* Sync, bool* Reserve) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Database::Info", _("Database is not connected.")); + + char items[] = {isc_info_ods_version, + isc_info_ods_minor_version, + isc_info_page_size, + isc_info_allocation, + isc_info_num_buffers, + isc_info_sweep_interval, + isc_info_forced_writes, + isc_info_no_reserve, + isc_info_end}; + IBS status; + RB result(256); + + status.Reset(); + (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items, + result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Database::Info", _("isc_database_info failed")); + + if (ODSMajor != 0) *ODSMajor = result.GetValue(isc_info_ods_version); + if (ODSMinor != 0) *ODSMinor = result.GetValue(isc_info_ods_minor_version); + if (PageSize != 0) *PageSize = result.GetValue(isc_info_page_size); + if (Pages != 0) *Pages = result.GetValue(isc_info_allocation); + if (Buffers != 0) *Buffers = result.GetValue(isc_info_num_buffers); + if (Sweep != 0) *Sweep = result.GetValue(isc_info_sweep_interval); + if (Sync != 0) + *Sync = result.GetValue(isc_info_forced_writes) == 1 ? true : false; + if (Reserve != 0) + *Reserve = result.GetValue(isc_info_no_reserve) == 1 ? false : true; +} + +void DatabaseImpl::Statistics(int* Fetches, int* Marks, int* Reads, int* Writes) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Database::Statistics", _("Database is not connected.")); + + char items[] = {isc_info_fetches, + isc_info_marks, + isc_info_reads, + isc_info_writes, + isc_info_end}; + IBS status; + RB result(128); + + status.Reset(); + (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items, + result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Database::Statistics", _("isc_database_info failed")); + + if (Fetches != 0) *Fetches = result.GetValue(isc_info_fetches); + if (Marks != 0) *Marks = result.GetValue(isc_info_marks); + if (Reads != 0) *Reads = result.GetValue(isc_info_reads); + if (Writes != 0) *Writes = result.GetValue(isc_info_writes); +} + +void DatabaseImpl::Counts(int* Insert, int* Update, int* Delete, + int* ReadIdx, int* ReadSeq) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Database::Counts", _("Database is not connected.")); + + char items[] = {isc_info_insert_count, + isc_info_update_count, + isc_info_delete_count, + isc_info_read_idx_count, + isc_info_read_seq_count, + isc_info_end}; + IBS status; + RB result(1024); + + status.Reset(); + (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items, + result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Database::Counts", _("isc_database_info failed")); + + if (Insert != 0) *Insert = result.GetCountValue(isc_info_insert_count); + if (Update != 0) *Update = result.GetCountValue(isc_info_update_count); + if (Delete != 0) *Delete = result.GetCountValue(isc_info_delete_count); + if (ReadIdx != 0) *ReadIdx = result.GetCountValue(isc_info_read_idx_count); + if (ReadSeq != 0) *ReadSeq = result.GetCountValue(isc_info_read_seq_count); +} + +void DatabaseImpl::Users(std::vector& users) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Database::Users", _("Database is not connected.")); + + char items[] = {isc_info_user_names, + isc_info_end}; + IBS status; + RB result(8000); + + status.Reset(); + (*gds.Call()->m_database_info)(status.Self(), &mHandle, sizeof(items), items, + result.Size(), result.Self()); + if (status.Errors()) + { + status.Reset(); + throw SQLExceptionImpl(status, "Database::Users", _("isc_database_info failed")); + } + + users.clear(); + char* p = result.Self(); + while (*p == isc_info_user_names) + { + p += 3; // Get to the length byte (there are two undocumented bytes which we skip) + int len = (int)(*p); + ++p; // Get to the first char of username + if (len != 0) users.push_back(std::string().append(p, len)); + p += len; // Skip username + } + return; +} + +IBPP::IDatabase* DatabaseImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + return this; +} + +void DatabaseImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void DatabaseImpl::AttachTransactionImpl(TransactionImpl* tr) +{ + if (tr == 0) + throw LogicExceptionImpl("Database::AttachTransaction", + _("Transaction object is null.")); + + mTransactions.push_back(tr); +} + +void DatabaseImpl::DetachTransactionImpl(TransactionImpl* tr) +{ + if (tr == 0) + throw LogicExceptionImpl("Database::DetachTransaction", + _("ITransaction object is null.")); + + mTransactions.erase(std::find(mTransactions.begin(), mTransactions.end(), tr)); +} + +void DatabaseImpl::AttachStatementImpl(StatementImpl* st) +{ + if (st == 0) + throw LogicExceptionImpl("Database::AttachStatement", + _("Can't attach a null Statement object.")); + + mStatements.push_back(st); +} + +void DatabaseImpl::DetachStatementImpl(StatementImpl* st) +{ + if (st == 0) + throw LogicExceptionImpl("Database::DetachStatement", + _("Can't detach a null Statement object.")); + + mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st)); +} + +void DatabaseImpl::AttachBlobImpl(BlobImpl* bb) +{ + if (bb == 0) + throw LogicExceptionImpl("Database::AttachBlob", + _("Can't attach a null Blob object.")); + + mBlobs.push_back(bb); +} + +void DatabaseImpl::DetachBlobImpl(BlobImpl* bb) +{ + if (bb == 0) + throw LogicExceptionImpl("Database::DetachBlob", + _("Can't detach a null Blob object.")); + + mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb)); +} + +void DatabaseImpl::AttachArrayImpl(ArrayImpl* ar) +{ + if (ar == 0) + throw LogicExceptionImpl("Database::AttachArray", + _("Can't attach a null Array object.")); + + mArrays.push_back(ar); +} + +void DatabaseImpl::DetachArrayImpl(ArrayImpl* ar) +{ + if (ar == 0) + throw LogicExceptionImpl("Database::DetachArray", + _("Can't detach a null Array object.")); + + mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar)); +} + +void DatabaseImpl::AttachEventsImpl(EventsImpl* ev) +{ + if (ev == 0) + throw LogicExceptionImpl("Database::AttachEventsImpl", + _("Can't attach a null Events object.")); + + mEvents.push_back(ev); +} + +void DatabaseImpl::DetachEventsImpl(EventsImpl* ev) +{ + if (ev == 0) + throw LogicExceptionImpl("Database::DetachEventsImpl", + _("Can't detach a null Events object.")); + + mEvents.erase(std::find(mEvents.begin(), mEvents.end(), ev)); +} + +DatabaseImpl::DatabaseImpl(const std::string& ServerName, const std::string& DatabaseName, + const std::string& UserName, const std::string& UserPassword, + const std::string& RoleName, const std::string& CharSet, + const std::string& CreateParams) : + + mRefCount(0), mHandle(0), + mServerName(ServerName), mDatabaseName(DatabaseName), + mUserName(UserName), mUserPassword(UserPassword), mRoleName(RoleName), + mCharSet(CharSet), mCreateParams(CreateParams), + mDialect(3) +{ +} + +DatabaseImpl::~DatabaseImpl() +{ + try { if (Connected()) Disconnect(); } + catch(...) { } +} + +// +// EOF +// diff --git a/libs/ibpp/date.cpp b/libs/ibpp/date.cpp new file mode 100644 index 00000000..f4838240 --- /dev/null +++ b/libs/ibpp/date.cpp @@ -0,0 +1,209 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: date.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $ +// Subject : IBPP, Date class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include // Can't use thanks to MSVC6 buggy library + +using namespace ibpp_internals; + +void IBPP::Date::Today() +{ + time_t systime = time(0); + tm* loctime = localtime(&systime); + + if (! IBPP::itod(&mDate, loctime->tm_year + 1900, + loctime->tm_mon + 1, loctime->tm_mday)) + throw LogicExceptionImpl("Date::Today", _("Out of range")); +} + +void IBPP::Date::SetDate(int dt) +{ + if (! IBPP::dtoi(dt, 0, 0, 0)) + throw LogicExceptionImpl("Date::SetDate", _("Out of range")); + mDate = dt; +} + +void IBPP::Date::SetDate(int year, int month, int day) +{ + if (! IBPP::itod(&mDate, year, month, day)) + throw LogicExceptionImpl("Date::SetDate", _("Out of range")); +} + +void IBPP::Date::GetDate(int& year, int& month, int& day) const +{ + if (! IBPP::dtoi(mDate, &year, &month, &day)) + throw LogicExceptionImpl("Date::GetDate", _("Out of range")); +} + +int IBPP::Date::Year() const +{ + int year; + if (! IBPP::dtoi(mDate, &year, 0, 0)) + throw LogicExceptionImpl("Date::Year", _("Out of range")); + return year; +} + +int IBPP::Date::Month() const +{ + int month; + if (! IBPP::dtoi(mDate, 0, &month, 0)) + throw LogicExceptionImpl("Date::Month", _("Out of range")); + return month; +} + +int IBPP::Date::Day() const +{ + int day; + if (! IBPP::dtoi(mDate, 0, 0, &day)) + throw LogicExceptionImpl("Date::Day", _("Out of range")); + return day; +} + +void IBPP::Date::Add(int days) +{ + int newdate = mDate + days; // days can be signed + if (! IBPP::dtoi(newdate, 0, 0, 0)) + throw LogicExceptionImpl("Date::Add()", _("Out of range")); + mDate = newdate; +} + +void IBPP::Date::StartOfMonth() +{ + int year, month; + if (! IBPP::dtoi(mDate, &year, &month, 0)) + throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range")); + if (! IBPP::itod(&mDate, year, month, 1)) // First of same month + throw LogicExceptionImpl("Date::StartOfMonth()", _("Out of range")); +} + +void IBPP::Date::EndOfMonth() +{ + int year, month; + if (! IBPP::dtoi(mDate, &year, &month, 0)) + throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range")); + if (++month > 12) { month = 1; year++; } + if (! IBPP::itod(&mDate, year, month, 1)) // First of next month + throw LogicExceptionImpl("Date::EndOfMonth()", _("Out of range")); + mDate--; // Last day of original month, all weird cases accounted for +} + +IBPP::Date::Date(int year, int month, int day) +{ + SetDate(year, month, day); +} + +IBPP::Date::Date(const IBPP::Date& copied) +{ + mDate = copied.mDate; +} + +IBPP::Date& IBPP::Date::operator=(const IBPP::Timestamp& assigned) +{ + mDate = assigned.GetDate(); + return *this; +} + +IBPP::Date& IBPP::Date::operator=(const IBPP::Date& assigned) +{ + mDate = assigned.mDate; + return *this; +} + +// The following date calculations were inspired by web pages found on +// Peter Baum web homepage at 'http://www.capecod.net/~pbaum/'. +// His contact info is at : 'http://home.capecod.net/~pbaum/contact.htm'. +// Please, understand that Peter Baum is not related to this IBPP project. +// So __please__, do not contact him regarding IBPP matters. + +// Take a date, in its integer format as used in IBPP internals and splits +// it in year (4 digits), month (1-12), day (1-31) + +bool IBPP::dtoi (int date, int *y, int *m, int *d) +{ + int RataDie, Z, H, A, B, C; + int year, month, day; + + // Validity control. + if (date < IBPP::MinDate || date > IBPP::MaxDate) + return false; + + // The "Rata Die" is the date specified as the number of days elapsed since + // 31 Dec of year 0. So 1 Jan 0001 is 1. + + RataDie = date + ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899. + + Z = RataDie + 306; + H = 100*Z - 25; + A = H/3652425; + B = A - A/4; + year = (100*B + H) / 36525; + C = B + Z - 365*year - year / 4; + month = (5*C + 456) / 153; + day = C - (153*month - 457) / 5; + if (month > 12) { year += 1; month -= 12; } + + if (y != 0) *y = (int)year; + if (m != 0) *m = (int)month; + if (d != 0) *d = (int)day; + + return true; +} + +// Take a date from its components year, month, day and convert it to the +// integer representation used internally in IBPP. + +bool IBPP::itod (int *pdate, int year, int month, int day) +{ + int RataDie, result; + int y, m, d; + + d = day; m = month; y = year; + if (m < 3) { m += 12; y -= 1; } + RataDie = d + (153*m - 457) / 5 + 365*y + y/4 - y/100 + y/400 - 306; + + result = RataDie - ibpp_internals::consts::Dec31_1899; // Because IBPP sets the '0' on 31 Dec 1899 + + // Validity control + if (result < IBPP::MinDate || result > IBPP::MaxDate) + return false; + + *pdate = result; + return true; +} + +// Eof diff --git a/libs/ibpp/dbkey.cpp b/libs/ibpp/dbkey.cpp new file mode 100644 index 00000000..080b4d77 --- /dev/null +++ b/libs/ibpp/dbkey.cpp @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: dbkey.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $ +// Subject : IBPP, DBKey class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include +#include +#include + +using namespace ibpp_internals; + +// Private implementation + +// Public implementation + +void IBPP::DBKey::Clear() +{ + mDBKey.erase(); + mString.erase(); +} + +void IBPP::DBKey::SetKey(const void* key, int size) +{ + if (key == 0) + throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Null DBKey reference detected.")); + if (size <= 0 || ((size >> 3) << 3) != size) + throw LogicExceptionImpl("IBPP::DBKey::SetKey", _("Invalid DBKey size.")); + + mDBKey.assign((const char*)key, (size_t)size); + mString.erase(); +} + +void IBPP::DBKey::GetKey(void* key, int size) const +{ + if (mDBKey.empty()) + throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("DBKey not assigned.")); + if (key == 0) + throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Null DBKey reference detected.")); + if (size != (int)mDBKey.size()) + throw LogicExceptionImpl("IBPP::DBKey::GetKey", _("Incompatible DBKey size detected.")); + + mDBKey.copy((char*)key, mDBKey.size()); +} + +const char* IBPP::DBKey::AsString() const +{ + if (mDBKey.empty()) + throw LogicExceptionImpl("IBPP::DBKey::GetString", _("DBKey not assigned.")); + + if (mString.empty()) + { + std::ostringstream hexkey; + hexkey.setf(std::ios::hex, std::ios::basefield); + hexkey.setf(std::ios::uppercase); + + const uint32_t* key = reinterpret_cast(mDBKey.data()); + int n = (int)mDBKey.size() / 8; + for (int i = 0; i < n; i++) + { + if (i != 0) hexkey<< "-"; + hexkey<< std::setw(4)<< key[i*2]<< ":"; + hexkey<< std::setw(8)<< key[i*2+1]; + } + + mString = hexkey.str(); + } + + return mString.c_str(); +} + +IBPP::DBKey::DBKey(const DBKey& copied) +{ + mDBKey = copied.mDBKey; + mString = copied.mString; +} + +IBPP::DBKey& IBPP::DBKey::operator=(const IBPP::DBKey& assigned) +{ + mDBKey = assigned.mDBKey; + mString = assigned.mString; + return *this; +} + +// +// EOF +// diff --git a/libs/ibpp/events.cpp b/libs/ibpp/events.cpp new file mode 100644 index 00000000..14ce1baa --- /dev/null +++ b/libs/ibpp/events.cpp @@ -0,0 +1,372 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: events.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $ +// Subject : IBPP, internal EventsImpl class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +// SPECIAL WARNING COMMENT (by Olivier Mascia, 2000 Nov 12) +// The way this source file handles events is not publicly documented, in +// the ibase.h header file or in the IB 6.0 documentation. This documentation +// suggests to use the API isc_event_block to construct vectors of events. +// Unfortunately, this API takes a variable number of parameters to specify +// the list of event names. In addition, the documentation warn on not using +// more than 15 names. This is a sad limitation, partly because the maximum +// number of parameters safely processed in such an API is very compiler +// dependant and also because isc_event_counts() is designed to return counts +// through the IB status vector which is a vector of 20 32-bits integers ! +// From reverse engineering of the isc_event_block() API in +// source file jrd/alt.c (as available on fourceforge.net/project/InterBase as +// of 2000 Nov 12), it looks like the internal format of those EPB is simple. +// An EPB starts by a byte with value 1. A version identifier of some sort. +// Then a small cluster is used for each event name. The cluster starts with +// a byte for the length of the event name (no final '\0'). Followed by the N +// characters of the name itself (no final '\0'). The cluster ends with 4 bytes +// preset to 0. +// +// SPECIAL CREDIT (July 2004) : this is a complete re-implementation of this +// class, directly based on work by Val Samko. +// The whole event handling has then be completely redesigned, based on the old +// EPB class to bring up the current IBPP::Events implementation. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +using namespace ibpp_internals; + +const size_t EventsImpl::MAXEVENTNAMELEN = 127; + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void EventsImpl::Add(const std::string& eventname, IBPP::EventInterface* objref) +{ + if (eventname.size() == 0) + throw LogicExceptionImpl("Events::Add", _("Zero length event names not permitted")); + if (eventname.size() > MAXEVENTNAMELEN) + throw LogicExceptionImpl("Events::Add", _("Event name is too long")); + if ((mEventBuffer.size() + eventname.length() + 5) > 32766) // max signed 16 bits integer minus one + throw LogicExceptionImpl("Events::Add", + _("Can't add this event, the events list would overflow IB/FB limitation")); + + Cancel(); + + // 1) Alloc or grow the buffers + size_t prev_buffer_size = mEventBuffer.size(); + size_t needed = ((prev_buffer_size==0) ? 1 : 0) + eventname.length() + 5; + // Initial alloc will require one more byte, we need 4 more bytes for + // the count itself, and one byte for the string length prefix + + mEventBuffer.resize(mEventBuffer.size() + needed); + mResultsBuffer.resize(mResultsBuffer.size() + needed); + if (prev_buffer_size == 0) + mEventBuffer[0] = mResultsBuffer[0] = 1; // First byte is a 'one'. Documentation ?? + + // 2) Update the buffers (append) + { + Buffer::iterator it = mEventBuffer.begin() + + ((prev_buffer_size==0) ? 1 : prev_buffer_size); // Byte after current content + *(it++) = static_cast(eventname.length()); + it = std::copy(eventname.begin(), eventname.end(), it); + // We initialize the counts to (uint32_t)(-1) to initialize properly, see FireActions() + *(it++) = -1; *(it++) = -1; *(it++) = -1; *it = -1; + } + + // copying new event to the results buffer to keep event_buffer_ and results_buffer_ consistant, + // otherwise we might get a problem in `FireActions` + // Val Samko, val@digiways.com + std::copy(mEventBuffer.begin() + prev_buffer_size, + mEventBuffer.end(), mResultsBuffer.begin() + prev_buffer_size); + + // 3) Alloc or grow the objref array and update the objref array (append) + mObjectReferences.push_back(objref); + + Queue(); +} + +void EventsImpl::Drop(const std::string& eventname) +{ + if (eventname.size() == 0) + throw LogicExceptionImpl("EventsImpl::Drop", _("Zero length event names not permitted")); + if (eventname.size() > MAXEVENTNAMELEN) + throw LogicExceptionImpl("EventsImpl::Drop", _("Event name is too long")); + + if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error + + Cancel(); + + // 1) Find the event in the buffers + typedef EventBufferIterator EventIterator; + EventIterator eit(mEventBuffer.begin()+1); + EventIterator rit(mResultsBuffer.begin()+1); + + for (ObjRefs::iterator oit = mObjectReferences.begin(); + oit != mObjectReferences.end(); + ++oit, ++eit, ++rit) + { + if (eventname != eit.get_name()) continue; + + // 2) Event found, remove it + mEventBuffer.erase(eit.begin(), eit.end()); + mResultsBuffer.erase(rit.begin(), rit.end()); + mObjectReferences.erase(oit); + break; + } + + Queue(); +} + +void EventsImpl::List(std::vector& events) +{ + events.clear(); + + if (mEventBuffer.size() <= 1) return; // Nothing to do, but not an error + + typedef EventBufferIterator EventIterator; + EventIterator eit(mEventBuffer.begin()+1); + + for (ObjRefs::iterator oit = mObjectReferences.begin(); + oit != mObjectReferences.end(); + ++oit, ++eit) + { + events.push_back(eit.get_name()); + } +} + +void EventsImpl::Clear() +{ + Cancel(); + + mObjectReferences.clear(); + mEventBuffer.clear(); + mResultsBuffer.clear(); +} + +void EventsImpl::Dispatch() +{ + // If no events registered, nothing to do of course. + if (mEventBuffer.size() == 0) return; + + // Let's fire the events actions for all the events which triggered, if any, and requeue. + FireActions(); + Queue(); +} + +IBPP::Database EventsImpl::DatabasePtr() const +{ + if (mDatabase == 0) throw LogicExceptionImpl("Events::DatabasePtr", + _("No Database is attached.")); + return mDatabase; +} + +IBPP::IEvents* EventsImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + return this; +} + +void EventsImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void EventsImpl::Queue() +{ + if (! mQueued) + { + if (mDatabase->GetHandle() == 0) + throw LogicExceptionImpl("EventsImpl::Queue", + _("Database is not connected")); + + IBS vector; + mTrapped = false; + mQueued = true; + (*gds.Call()->m_que_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId, + short(mEventBuffer.size()), &mEventBuffer[0], + (isc_callback)EventHandler, (char*)this); + + if (vector.Errors()) + { + mId = 0; // Should be, but better be safe + mQueued = false; + throw SQLExceptionImpl(vector, "EventsImpl::Queue", + _("isc_que_events failed")); + } + } +} + +void EventsImpl::Cancel() +{ + if (mQueued) + { + if (mDatabase->GetHandle() == 0) throw LogicExceptionImpl("EventsImpl::Cancel", + _("Database is not connected")); + + IBS vector; + + // A call to cancel_events will call *once* the handler routine, even + // though no events had fired. This is why we first set mEventsQueued + // to false, so that we can be sure to dismiss those unwanted callbacks + // subsequent to the execution of isc_cancel_events(). + mTrapped = false; + mQueued = false; + (*gds.Call()->m_cancel_events)(vector.Self(), mDatabase->GetHandlePtr(), &mId); + + if (vector.Errors()) + { + mQueued = true; // Need to restore this as cancel failed + throw SQLExceptionImpl(vector, "EventsImpl::Cancel", + _("isc_cancel_events failed")); + } + + mId = 0; // Should be, but better be safe + } +} + +void EventsImpl::FireActions() +{ + if (mTrapped) + { + typedef EventBufferIterator EventIterator; + EventIterator eit(mEventBuffer.begin()+1); + EventIterator rit(mResultsBuffer.begin()+1); + + for (ObjRefs::iterator oit = mObjectReferences.begin(); + oit != mObjectReferences.end(); + ++oit, ++eit, ++rit) + { + if (eit == EventIterator(mEventBuffer.end()) + || rit == EventIterator(mResultsBuffer.end())) + throw LogicExceptionImpl("EventsImpl::FireActions", _("Internal buffer size error")); + uint32_t vnew = rit.get_count(); + uint32_t vold = eit.get_count(); + if (vnew > vold) + { + // Fire the action + try + { + (*oit)->ibppEventHandler(this, eit.get_name(), (int)(vnew - vold)); + } + catch (...) + { + std::copy(rit.begin(), rit.end(), eit.begin()); + throw; + } + std::copy(rit.begin(), rit.end(), eit.begin()); + } + // This handles initialization too, where vold == (uint32_t)(-1) + // Thanks to M. Hieke for this idea and related initialization to (-1) + if (vnew != vold) + std::copy(rit.begin(), rit.end(), eit.begin()); + } + } +} + +// This function must keep this prototype to stay compatible with +// what isc_que_events() expects + +void EventsImpl::EventHandler(const char* object, short size, const char* tmpbuffer) +{ + // >>>>> This method is a STATIC member !! <<<<< + // Consider this method as a kind of "interrupt handler". It should do as + // few work as possible as quickly as possible and then return. + // Never forget: this is called by the Firebird client code, on *some* + // thread which might not be (and won't probably be) any of your application + // thread. This function is to be considered as an "interrupt-handler" of a + // hardware driver. + + // There can be spurious calls to EventHandler from FB internal. We must + // dismiss those calls. + if (object == 0 || size == 0 || tmpbuffer == 0) return; + + EventsImpl* evi = (EventsImpl*)object; // Ugly, but wanted, c-style cast + + if (evi->mQueued) + { + try + { + char* rb = &evi->mResultsBuffer[0]; + if (evi->mEventBuffer.size() < (unsigned)size) size = (short)evi->mEventBuffer.size(); + for (int i = 0; i < size; i++) + rb[i] = tmpbuffer[i]; + evi->mTrapped = true; + evi->mQueued = false; + } + catch (...) { } + } +} + +void EventsImpl::AttachDatabaseImpl(DatabaseImpl* database) +{ + if (database == 0) throw LogicExceptionImpl("EventsImpl::AttachDatabase", + _("Can't attach a null Database object.")); + + if (mDatabase != 0) mDatabase->DetachEventsImpl(this); + mDatabase = database; + mDatabase->AttachEventsImpl(this); +} + +void EventsImpl::DetachDatabaseImpl() +{ + if (mDatabase == 0) return; + + mDatabase->DetachEventsImpl(this); + mDatabase = 0; +} + +EventsImpl::EventsImpl(DatabaseImpl* database) + : mRefCount(0) +{ + mDatabase = 0; + mId = 0; + mQueued = mTrapped = false; + AttachDatabaseImpl(database); +} + +EventsImpl::~EventsImpl() +{ + try { Clear(); } + catch (...) { } + + try { if (mDatabase != 0) mDatabase->DetachEventsImpl(this); } + catch (...) { } +} + +// +// EOF +// diff --git a/libs/ibpp/exception.cpp b/libs/ibpp/exception.cpp new file mode 100644 index 00000000..aa47e285 --- /dev/null +++ b/libs/ibpp/exception.cpp @@ -0,0 +1,351 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: exception.cpp,v 1.1 2007/05/05 17:00:42 faust Exp $ +// Subject : IBPP, Initialization of the library +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include +#include + +using namespace ibpp_internals; + +// None of the exception classes methods are implemented inline, because they +// are all declared throw() and Borland compilers at least, but possibly some +// others emit a warning like "W8026 - functions with exception specification +// are not expanded inline". Nothing we have to worry about, but we don't want +// people concerned by such warnings. + +IBPP::Exception::~Exception() throw() +{ +} + +IBPP::LogicException::~LogicException() throw() +{ +} + +IBPP::SQLException::~SQLException() throw() +{ +} + +IBPP::WrongType::~WrongType() throw() +{ +} + +// +// (((((((( ExceptionBase Implementation )))))))) +// + +void ExceptionBase::buildErrorMessage(const char* message) +{ + if (! mContext.empty()) + mWhat.append(_("Context: ")).append(mContext).append("\n"); + + if (message != 0 && *message != 0 ) + mWhat.append(_("Message: ")).append(message).append("\n"); + + mWhat.append("\n"); +} + +void ExceptionBase::raise(const std::string& context, const char* message, va_list argptr) +{ + mContext.assign(context); + + if (message != 0) + { + char buffer[1024]; +#if defined(_MSC_VER) || defined(__DMC__) + _vsnprintf(buffer, sizeof(buffer)-1, message, argptr); +#else + vsnprintf(buffer, sizeof(buffer)-1, message, argptr); +#endif + buffer[sizeof(buffer)-1] = 0; + + buildErrorMessage(buffer); + } + else + buildErrorMessage(0); +} + +ExceptionBase::ExceptionBase() throw() +{ +} + +ExceptionBase::ExceptionBase(const ExceptionBase& copied) throw() +{ + mContext = copied.mContext; + mWhat = copied.mWhat; +} + +ExceptionBase& ExceptionBase::operator=(const ExceptionBase& copied) throw() +{ + mContext = copied.mContext; + mWhat = copied.mWhat; + return *this; +} + +ExceptionBase::ExceptionBase(const std::string& context, + const char* message, ...) throw() +{ + va_list argptr; + va_start(argptr, message); + mWhat.assign("*** IBPP::Exception ***\n"); + raise(context, message, argptr); + va_end(argptr); +} + +ExceptionBase::~ExceptionBase() throw() +{ +} + +const char* ExceptionBase::Origin() const throw() +{ + return mContext.c_str(); +} + +const char* ExceptionBase::ErrorMessage() const throw() +{ + return mWhat.c_str(); +} + +const char* ExceptionBase::what() const throw() +{ + return mWhat.c_str(); +} + +// (((((((( LogicExceptionImpl Implementation )))))))) + +// The following constructors are small and could be inlined, but for object +// code compacity of the library it is much better to have them non-inlined. +// The amount of code generated by compilers for a throw is well-enough. + +LogicExceptionImpl::LogicExceptionImpl() throw() + : ExceptionBase() +{ +} + +LogicExceptionImpl::LogicExceptionImpl(const LogicExceptionImpl& copied) throw() + : IBPP::LogicException(), ExceptionBase(copied) +{ +} + +LogicExceptionImpl& LogicExceptionImpl::operator=(const LogicExceptionImpl& copied) throw() +{ + ExceptionBase::operator=(copied); + return *this; +} + +LogicExceptionImpl::LogicExceptionImpl(const std::string& context, + const char* message, ...) throw() +{ + va_list argptr; + va_start(argptr, message); + mWhat.assign("*** IBPP::LogicException ***\n"); + raise(context, message, argptr); + va_end(argptr); +} + +LogicExceptionImpl::~LogicExceptionImpl() throw () +{ +} + +const char* LogicExceptionImpl::Origin() const throw() +{ + return ExceptionBase::Origin(); +} + +const char* LogicExceptionImpl::ErrorMessage() const throw() +{ + return ExceptionBase::what(); +} + +const char* LogicExceptionImpl::what() const throw() +{ + return ExceptionBase::what(); +} + +// (((((((( SQLExceptionImpl Implementation )))))))) + +SQLExceptionImpl::SQLExceptionImpl() throw() + : ExceptionBase(), mSqlCode(0), mEngineCode(0) +{ +} + +SQLExceptionImpl::SQLExceptionImpl(const SQLExceptionImpl& copied) throw() + : IBPP::SQLException(), ExceptionBase(copied), mSqlCode(copied.mSqlCode), + mEngineCode(copied.mEngineCode) +{ +} + +SQLExceptionImpl& SQLExceptionImpl::operator=(const SQLExceptionImpl& copied) throw() +{ + ExceptionBase::operator=(copied); + mSqlCode = copied.mSqlCode; + mEngineCode = copied.mEngineCode; + return *this; +} + +SQLExceptionImpl::SQLExceptionImpl(const IBS& status, const std::string& context, + const char* message, ...) throw() +{ + va_list argptr; + va_start(argptr, message); + mWhat.assign("*** IBPP::SQLException ***\n"); + raise(context, message, argptr); + va_end(argptr); + mSqlCode = status.SqlCode(); + mEngineCode = status.EngineCode(); + mWhat.append(status.ErrorMessage()); +} + +SQLExceptionImpl::~SQLExceptionImpl() throw () +{ +} + +const char* SQLExceptionImpl::Origin() const throw() +{ + return ExceptionBase::Origin(); +} + +const char* SQLExceptionImpl::ErrorMessage() const throw() +{ + return ExceptionBase::what(); +} + +const char* SQLExceptionImpl::what() const throw() +{ + return ExceptionBase::what(); +} + +int SQLExceptionImpl::SqlCode() const throw() +{ + return mSqlCode; +} + +int SQLExceptionImpl::EngineCode() const throw() +{ + return mEngineCode; +} + +// (((((((( WrongTypeImpl Implementation )))))))) + +// The following constructors are small and could be inlined, but for object +// code compacity of the library it is much better to have them non-inlined. +// The amount of code generated by compilers for a throw is well-enough. + +WrongTypeImpl::WrongTypeImpl() throw() + : IBPP::WrongType(), ExceptionBase() +{ +} + +WrongTypeImpl::WrongTypeImpl(const WrongTypeImpl& copied) throw() + : IBPP::WrongType(), ExceptionBase(copied) +{ +} + +WrongTypeImpl& WrongTypeImpl::operator=(const WrongTypeImpl& copied) throw() +{ + ExceptionBase::operator=(copied); + return *this; +} + +WrongTypeImpl::WrongTypeImpl(const std::string& context, int sqlType, IITYPE varType, + const char* message, ...) throw() +{ + va_list argptr; + va_start(argptr, message); + mWhat.assign("*** IBPP::WrongType ***\n"); + raise(context, message, argptr); + va_end(argptr); + + std::string info; + switch (sqlType & ~1) + { + case SQL_TEXT : info.append("CHAR"); break; + case SQL_VARYING : info.append("VARCHAR"); break; + case SQL_SHORT : info.append("SMALLINT"); break; + case SQL_LONG : info.append("INTEGER"); break; + case SQL_INT64 : info.append("BIGINT"); break; + case SQL_FLOAT : info.append("FLOAT"); break; + case SQL_DOUBLE : info.append("DOUBLE"); break; + case SQL_TIMESTAMP : info.append("TIMESTAMP"); break; + case SQL_TYPE_DATE : info.append("DATE"); break; + case SQL_TYPE_TIME : info.append("TIME"); break; + case SQL_BLOB : info.append("BLOB"); break; + case SQL_ARRAY : info.append("ARRAY"); break; + } + info.append(" ").append(_(" and ")).append(" "); + switch (varType) + { + case ivArray : info.append("Array"); break; + case ivBlob : info.append("Blob"); break; + case ivDate : info.append("Date"); break; + case ivTime : info.append("Time"); break; + case ivTimestamp : info.append("Timestamp"); break; + case ivString : info.append("std::string"); break; + case ivInt16 : info.append("int16_t"); break; + case ivInt32 : info.append("int32_t"); break; + case ivInt64 : info.append("int64_t"); break; + case ivFloat : info.append("float"); break; + case ivDouble : info.append("double"); break; + case ivBool : info.append("bool"); break; + case ivDBKey : info.append("DBKey"); break; + case ivByte : info.append("int8_t"); break; + } + mWhat.append(info).append("\n"); +} + +WrongTypeImpl::~WrongTypeImpl() throw () +{ +} + +const char* WrongTypeImpl::Origin() const throw() +{ + return ExceptionBase::Origin(); +} + +const char* WrongTypeImpl::ErrorMessage() const throw() +{ + return ExceptionBase::what(); +} + +const char* WrongTypeImpl::what() const throw() +{ + return ExceptionBase::what(); +} + +// +// EOF +// diff --git a/libs/ibpp/ibase.h b/libs/ibpp/ibase.h new file mode 100644 index 00000000..9c43ba20 --- /dev/null +++ b/libs/ibpp/ibase.h @@ -0,0 +1,2853 @@ +/* + * MODULE: ibase.h + * DESCRIPTION: OSRI entrypoints and defines + * + * The contents of this file are subject to the Interbase Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy + * of the License at http://www.Inprise.com/IPL.html + * + * Software distributed under the License is distributed on an + * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express + * or implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code was created by Inprise Corporation + * and its predecessors. Portions created by Inprise Corporation are + * Copyright (C) Inprise Corporation. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * Added TCP_NO_DELAY option for superserver on Linux + * FSG 16.03.2001 + * 2001.07.28: John Bellardo: Added blr_skip + * 2001.09.18: Ann Harrison: New info codes + * 17-Oct-2001 Mike Nordell: CPU affinity + * 2001-04-16 Paul Beach: ISC_TIME_SECONDS_PRECISION_SCALE modified for HP10 + * Compiler Compatibility + * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete ports: + * - EPSON, XENIX, MAC (MAC_AUX), Cray and OS/2 + * 2002.10.29 Nickolay Samofatov: Added support for savepoints + * + * 2002.10.29 Sean Leyne - Removed support for obsolete IPX/SPX Protocol + * + */ +/* +$Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $ + */ + +#ifndef JRD_IBASE_H +#define JRD_IBASE_H + + +/* + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License Version 2 or later (the + * "GPL"), in which case the provisions of the GPL are applicable + * instead of those above. You may obtain a copy of the Licence at + * http://www.gnu.org/copyleft/gpl.html + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Relevant for more details. + * + * This file was created by members of the firebird development team. + * All individual contributions remain the Copyright (C) of those + * individuals. Contributors to this file are either listed here or + * can be obtained from a CVS history command. + * + * All rights reserved. + * + * Contributor(s): + * Mike Nordel + * Mark O'Donohue + * + * + * $Id: ibase.h,v 1.2 2007/05/17 08:39:25 faust Exp $ + * + * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete "OS/2" port + * + */ + + +#ifndef INCLUDE_FB_TYPES_H +#define INCLUDE_FB_TYPES_H + + +/******************************************************************/ +/* Define type, export and other stuff based on c/c++ and Windows */ +/******************************************************************/ + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) +#ifndef __GNUC__ +typedef __int64 ISC_INT64; +typedef unsigned __int64 ISC_UINT64; +#define ISC_INT64_DEFINED +#endif +#define ISC_EXPORT __stdcall +#define ISC_EXPORT_VARARG __cdecl +#else +#define ISC_EXPORT +#define ISC_EXPORT_VARARG +#endif + +/*******************************************************************/ +/* 64 bit Integers */ +/*******************************************************************/ + +#ifdef ISC_INT64_DEFINED +#undef ISC_INT64_DEFINED +#else +//typedef long long int ISC_INT64; +//typedef unsigned long long int ISC_UINT64; +typedef int64_t ISC_INT64; +typedef uint64_t ISC_UINT64; +#endif + +// Nickolay: it is easier to assume that integer is at least 32-bit. +// This comes from limitation that we cannot reliably detect datatype size at +// compile time in cases when we do not control compilation (public headers) +// We are not going to support 16-bit platforms, right? +// +// Temporarly restrict new definition until ULONG clash with Windows +// type is solved. Win64 port is not possible before that point. +// Cannot use SIZEOF_LONG define here because we are in a public header +#if defined(_LP64) || defined(__LP64__) || defined(__arch64__) + /* EKU: Firebird requires (S)LONG to be 32 bit */ +# define LONG_DEFINED + typedef int SLONG; + typedef unsigned int ULONG; +#endif /* SIZEOF_LONG == 8 */ + + + +/* Basic data types */ + + +#ifdef NOT_USED_OR_REPLACED +typedef signed char SCHAR; +#else +/* TMN: TODO It seems SCHAR is used just about *everywhere* where a plain + * "char" is really intended. This currently forces us to this bad definition. + */ +typedef char SCHAR; +#endif + + +typedef unsigned char UCHAR; +typedef short SSHORT; +typedef unsigned short USHORT; + + +#ifndef LONG_DEFINED /* 32 bit */ +typedef long SLONG; +typedef unsigned long ULONG; +#else +#undef LONG_DEFINED +#endif + + +#ifndef SQUAD_DEFINED /* 64 bit */ +typedef struct { + SLONG high; + ULONG low; +} SQUAD; +#endif + + +#ifndef DEFINED_GDS_QUAD +#define DEFINED_GDS_QUAD +struct GDS_QUAD_t { + SLONG gds_quad_high; + ULONG gds_quad_low; +}; + +typedef struct GDS_QUAD_t GDS_QUAD; + +#endif /* DEFINED_GDS_QUAD */ + +// +// TMN: some misc data types from all over the place +// +struct vary +{ + USHORT vary_length; + char vary_string[1]; +}; +// TMN: Currently we can't do this, since remote uses a different +// definition of VARY than the rest of the code! :-< +//typedef vary* VARY; + +struct lstring +{ + ULONG lstr_length; + ULONG lstr_allocated; + UCHAR* lstr_address; +}; +typedef struct lstring LSTRING; + + +typedef unsigned char BOOLEAN; +typedef char TEXT; // To be expunged over time +//typedef unsigned char STEXT; Signed text - not used +//typedef unsigned char UTEXT; Unsigned text - not used +typedef unsigned char BYTE; // Unsigned byte - common +//typedef char SBYTE; Signed byte - not used +typedef long ISC_STATUS; +typedef long IPTR; +typedef unsigned long U_IPTR; +typedef void (*FPTR_VOID) (); +typedef void (*FPTR_VOID_PTR) (void *); +typedef int (*FPTR_INT) (); +typedef int (*FPTR_INT_VOID_PTR) (void *); +typedef ULONG RCRD_OFFSET; +typedef USHORT FLD_LENGTH; +typedef int (*lock_ast_t)(void *); + +typedef IPTR FB_THREAD_ID; + +#define ISC_STATUS_LENGTH 20 +typedef ISC_STATUS ISC_STATUS_ARRAY[ISC_STATUS_LENGTH]; + +/* Number of elements in an arry */ +#define FB_NELEM(x) ((int)(sizeof(x) / sizeof(x[0]))) +#define FB_ALIGN(n,b) ((n+b-1)&~(b-1)) + +#endif /* INCLUDE_FB_TYPES_H */ + +#define FB_API_VER 15 +#define isc_version4 + +#define ISC_TRUE 1 +#define ISC_FALSE 0 +#if !(defined __cplusplus) +#define ISC__TRUE ISC_TRUE +#define ISC__FALSE ISC_FALSE +#endif + +#define ISC_FAR + +// It is difficult to detect 64-bit long from the redistributable header +// we do not care of 16-bit platforms anymore thus we may use plain "int" +// which is 32-bit on all platforms we support +#if defined(_LP64) || defined(__LP64__) || defined(__arch64__) +typedef int ISC_LONG; +typedef unsigned int ISC_ULONG; +#else +typedef signed long ISC_LONG; +typedef unsigned long ISC_ULONG; +#endif + +typedef signed short ISC_SHORT; +typedef unsigned short ISC_USHORT; + +typedef unsigned char ISC_UCHAR; + +#define DSQL_close 1 +#define DSQL_drop 2 + + +/********************************/ +/* InterBase Handle Definitions */ +/********************************/ + +#ifndef JRD_Y_REF_H +#define FRBRD void +#endif + +typedef FRBRD * isc_att_handle; +typedef FRBRD * isc_blob_handle; +typedef FRBRD * isc_db_handle; +typedef FRBRD * isc_req_handle; +typedef FRBRD * isc_stmt_handle; +typedef FRBRD * isc_svc_handle; +typedef FRBRD * isc_tr_handle; +typedef void (* isc_callback) (); +typedef ISC_LONG isc_resv_handle; + +/*******************************************************************/ +/* Time & Date Support */ +/*******************************************************************/ + +#ifndef ISC_TIMESTAMP_DEFINED +typedef int ISC_DATE; +typedef unsigned int ISC_TIME; +typedef struct +{ + ISC_DATE timestamp_date; + ISC_TIME timestamp_time; +} ISC_TIMESTAMP; +#define ISC_TIMESTAMP_DEFINED +#endif /* ISC_TIMESTAMP_DEFINED */ + +#define ISC_TIME_SECONDS_PRECISION 10000L +#define ISC_TIME_SECONDS_PRECISION_SCALE (-4) + +/*******************************************************************/ +/* Blob id structure */ +/*******************************************************************/ + +#if !(defined __cplusplus) +typedef GDS_QUAD GDS__QUAD; +#endif /* !(defined __cplusplus) */ + +typedef struct GDS_QUAD_t ISC_QUAD; + +#define isc_quad_high gds_quad_high +#define isc_quad_low gds_quad_low + +typedef struct +{ + short array_bound_lower; + short array_bound_upper; +} ISC_ARRAY_BOUND; + +typedef struct +{ + unsigned char array_desc_dtype; + char array_desc_scale; + unsigned short array_desc_length; + char array_desc_field_name[32]; + char array_desc_relation_name[32]; + short array_desc_dimensions; + short array_desc_flags; + ISC_ARRAY_BOUND array_desc_bounds[16]; +} ISC_ARRAY_DESC; + +typedef struct +{ + short blob_desc_subtype; + short blob_desc_charset; + short blob_desc_segment_size; + unsigned char blob_desc_field_name[32]; + unsigned char blob_desc_relation_name[32]; +} ISC_BLOB_DESC; + + + +/***************************/ +/* Blob control structure */ +/***************************/ + +typedef struct isc_blob_ctl +{ + ISC_STATUS (* ctl_source)(); /* Source filter */ + struct isc_blob_ctl * ctl_source_handle; /* Argument to pass to source filter */ + short ctl_to_sub_type; /* Target type */ + short ctl_from_sub_type; /* Source type */ + unsigned short ctl_buffer_length; /* Length of buffer */ + unsigned short ctl_segment_length; /* Length of current segment */ + unsigned short ctl_bpb_length; /* Length of blob parameter block */ + char * ctl_bpb; /* Address of blob parameter block */ + unsigned char * ctl_buffer; /* Address of segment buffer */ + ISC_LONG ctl_max_segment; /* Length of longest segment */ + ISC_LONG ctl_number_segments; /* Total number of segments */ + ISC_LONG ctl_total_length; /* Total length of blob */ + ISC_STATUS * ctl_status; /* Address of status vector */ + long ctl_data[8]; /* Application specific data */ +} * ISC_BLOB_CTL; + +/***************************/ +/* Blob stream definitions */ +/***************************/ + +typedef struct bstream +{ + isc_blob_handle bstr_blob; /* Blob handle */ + char * bstr_buffer; /* Address of buffer */ + char * bstr_ptr; /* Next character */ + short bstr_length; /* Length of buffer */ + short bstr_cnt; /* Characters in buffer */ + char bstr_mode; /* (mode) ? OUTPUT : INPUT */ +} BSTREAM; + +/* Three ugly macros, one even using octal radix... sigh... */ +#define getb(p) (--(p)->bstr_cnt >= 0 ? *(p)->bstr_ptr++ & 0377: BLOB_get (p)) +#define putb(x,p) (((x) == '\n' || (!(--(p)->bstr_cnt))) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x)))) +#define putbx(x,p) ((!(--(p)->bstr_cnt)) ? BLOB_put ((x),p) : ((int) (*(p)->bstr_ptr++ = (unsigned) (x)))) + + +/********************************************************************/ +/* CVC: Public blob interface definition held in val.h. */ +/* For some unknown reason, it was only documented in langRef */ +/* and being the structure passed by the engine to UDFs it never */ +/* made its way into this public definitions file. */ +/* Being its original name "blob", I renamed it blobcallback here. */ +/* I did the full definition with the proper parameters instead of */ +/* the weak C declaration with any number and type of parameters. */ +/* Since the first parameter -BLB- is unknown outside the engine, */ +/* it's more accurate to use void* than int* as the blob pointer */ +/********************************************************************/ + +#if !defined(JRD_VAL_H) && !defined(REQUESTER) +/* Blob passing structure */ + +enum lseek_mode {blb_seek_relative = 1, blb_seek_from_tail = 2}; + +typedef struct blobcallback { + short ( *blob_get_segment) + (void * hnd, unsigned char* buffer, ISC_USHORT buf_size, ISC_USHORT* result_len); + void *blob_handle; + ISC_LONG blob_number_segments; + ISC_LONG blob_max_segment; + ISC_LONG blob_total_length; + void ( *blob_put_segment) + (void * hnd, unsigned char* buffer, ISC_USHORT buf_size); + ISC_LONG ( *blob_lseek) + (void * hnd, ISC_USHORT mode, ISC_LONG offset); +} *BLOBCALLBACK; +#endif /* !defined(JRD_VAL_H) && !defined(REQUESTER) */ + + + +/********************************************************************/ +/* CVC: Public descriptor interface held in dsc.h. */ +/* We need it documented to be able to recognize NULL in UDFs. */ +/* Being its original name "dsc", I renamed it paramdsc here. */ +/* Notice that I adjust to the original definition: contrary to */ +/* other cases, the typedef is the same struct not the pointer. */ +/* I included the enumeration of dsc_dtype possible values. */ +/* Ultimately, dsc.h should be part of the public interface. */ +/********************************************************************/ + +#if !defined(JRD_DSC_H) +/* This is the famous internal descriptor that UDFs can use, too. */ +typedef struct paramdsc { + unsigned char dsc_dtype; + signed char dsc_scale; + ISC_USHORT dsc_length; + short dsc_sub_type; + ISC_USHORT dsc_flags; + unsigned char *dsc_address; +} PARAMDSC; + +#if !defined(JRD_VAL_H) +/* This is a helper struct to work with varchars. */ +typedef struct paramvary { + ISC_USHORT vary_length; + unsigned char vary_string [1]; +} PARAMVARY; +#endif /* !defined(JRD_VAL_H) */ + +/* values for dsc_flags */ +/* Note: DSC_null is only reliably set for local variables + (blr_variable) */ +#define DSC_null 1 +#define DSC_no_subtype 2 /* dsc has no sub type specified */ +#define DSC_nullable 4 /* not stored. instead, is derived + from metadata primarily to flag + SQLDA (in DSQL) */ + +/* Overload text typing information into the dsc_sub_type field. + See intl.h for definitions of text types */ + +#ifndef dsc_ttype +#define dsc_ttype dsc_sub_type +#endif + + +/* Note that dtype_null actually means that we do not yet know the + dtype for this descriptor. A nice cleanup item would be to globally + change it to dtype_unknown. --chrisj 1999-02-17 */ + +#define dtype_null 0 +#define dtype_text 1 +#define dtype_cstring 2 +#define dtype_varying 3 + +#define dtype_packed 6 +#define dtype_byte 7 +#define dtype_short 8 +#define dtype_long 9 +#define dtype_quad 10 +#define dtype_real 11 +#define dtype_double 12 +#define dtype_d_float 13 +#define dtype_sql_date 14 +#define dtype_sql_time 15 +#define dtype_timestamp 16 +#define dtype_blob 17 +#define dtype_array 18 +#define dtype_int64 19 +#define DTYPE_TYPE_MAX 20 +#endif /* !defined(JRD_DSC_H) */ + + +/***************************/ +/* Dynamic SQL definitions */ +/***************************/ + +/******************************/ +/* Declare the extended SQLDA */ +/******************************/ + +#ifndef FB_SQLDA + +typedef struct +{ + short sqltype; /* datatype of field */ + short sqlscale; /* scale factor */ + short sqlsubtype; /* datatype subtype - BLOBs & Text types only */ + short sqllen; /* length of data area */ + char * sqldata; /* address of data */ + short * sqlind; /* address of indicator variable */ + short sqlname_length; /* length of sqlname field */ + char sqlname[32]; /* name of field, name length + space for NULL */ + short relname_length; /* length of relation name */ + char relname[32]; /* field's relation name + space for NULL */ + short ownname_length; /* length of owner name */ + char ownname[32]; /* relation's owner name + space for NULL */ + short aliasname_length; /* length of alias name */ + char aliasname[32]; /* relation's alias name + space for NULL */ +} XSQLVAR; + +typedef struct +{ + short version; /* version of this XSQLDA */ + char sqldaid[8]; /* XSQLDA name field */ + ISC_LONG sqldabc; /* length in bytes of SQLDA */ + short sqln; /* number of fields allocated */ + short sqld; /* actual number of fields */ + XSQLVAR sqlvar[1]; /* first field address */ +} XSQLDA; + +#define XSQLDA_LENGTH(n) (sizeof (XSQLDA) + ((n)-1) * sizeof (XSQLVAR)) + +#define SQLDA_VERSION1 1 + +#define SQL_DIALECT_V5 1 /* meaning is same as DIALECT_xsqlda */ +#define SQL_DIALECT_V6_TRANSITION 2 /* flagging anything that is delimited + by double quotes as an error and + flagging keyword DATE as an error */ +#define SQL_DIALECT_V6 3 /* supports SQL delimited identifier, + SQLDATE/DATE, TIME, TIMESTAMP, + CURRENT_DATE, CURRENT_TIME, + CURRENT_TIMESTAMP, and 64-bit exact + numeric type */ +#define SQL_DIALECT_CURRENT SQL_DIALECT_V6 /* latest IB DIALECT */ + + +#define FB_SQLDA +#endif + +/***************************/ +/* OSRI database functions */ +/***************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +ISC_STATUS ISC_EXPORT isc_attach_database(ISC_STATUS *, + short, + char *, + isc_db_handle *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_array_gen_sdl(ISC_STATUS *, + ISC_ARRAY_DESC *, + short *, + char *, + short *); + +ISC_STATUS ISC_EXPORT isc_array_get_slice(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + ISC_QUAD *, + ISC_ARRAY_DESC *, + void *, + ISC_LONG *); + +ISC_STATUS ISC_EXPORT isc_array_lookup_bounds(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + char *, + char *, + ISC_ARRAY_DESC *); + +ISC_STATUS ISC_EXPORT isc_array_lookup_desc(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + char *, + char *, + ISC_ARRAY_DESC *); + +ISC_STATUS ISC_EXPORT isc_array_set_desc(ISC_STATUS *, + char *, + char *, + short *, + short *, + short *, + ISC_ARRAY_DESC *); + +ISC_STATUS ISC_EXPORT isc_array_put_slice(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + ISC_QUAD *, + ISC_ARRAY_DESC *, + void *, + ISC_LONG *); + +void ISC_EXPORT isc_blob_default_desc(ISC_BLOB_DESC *, + unsigned char *, + unsigned char *); + +ISC_STATUS ISC_EXPORT isc_blob_gen_bpb(ISC_STATUS *, + ISC_BLOB_DESC *, + ISC_BLOB_DESC *, + unsigned short, + unsigned char *, + unsigned short *); + +ISC_STATUS ISC_EXPORT isc_blob_info(ISC_STATUS *, + isc_blob_handle *, + short, + char *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_blob_lookup_desc(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned char *, + unsigned char *, + ISC_BLOB_DESC *, + unsigned char *); + +ISC_STATUS ISC_EXPORT isc_blob_set_desc(ISC_STATUS *, + unsigned char *, + unsigned char *, + short, + short, + short, + ISC_BLOB_DESC *); + +ISC_STATUS ISC_EXPORT isc_cancel_blob(ISC_STATUS *, + isc_blob_handle *); + +ISC_STATUS ISC_EXPORT isc_cancel_events(ISC_STATUS *, + isc_db_handle *, + ISC_LONG *); + +ISC_STATUS ISC_EXPORT isc_close_blob(ISC_STATUS *, + isc_blob_handle *); + +ISC_STATUS ISC_EXPORT isc_commit_retaining(ISC_STATUS *, + isc_tr_handle *); + +ISC_STATUS ISC_EXPORT isc_commit_transaction(ISC_STATUS *, + isc_tr_handle *); + +ISC_STATUS ISC_EXPORT isc_create_blob(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + isc_blob_handle *, + ISC_QUAD *); + +ISC_STATUS ISC_EXPORT isc_create_blob2(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + isc_blob_handle *, + ISC_QUAD *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_create_database(ISC_STATUS *, + short, + char *, + isc_db_handle *, + short, + char *, + short); + +ISC_STATUS ISC_EXPORT isc_database_info(ISC_STATUS *, + isc_db_handle *, + short, + char *, + short, + char *); + +void ISC_EXPORT isc_decode_date(ISC_QUAD *, + void *); + +void ISC_EXPORT isc_decode_sql_date(ISC_DATE *, + void *); + +void ISC_EXPORT isc_decode_sql_time(ISC_TIME *, + void *); + +void ISC_EXPORT isc_decode_timestamp(ISC_TIMESTAMP *, + void *); + +ISC_STATUS ISC_EXPORT isc_detach_database(ISC_STATUS *, + isc_db_handle *); + +ISC_STATUS ISC_EXPORT isc_drop_database(ISC_STATUS *, + isc_db_handle *); + +ISC_STATUS ISC_EXPORT isc_dsql_allocate_statement(ISC_STATUS *, + isc_db_handle *, + isc_stmt_handle *); + +ISC_STATUS ISC_EXPORT isc_dsql_alloc_statement2(ISC_STATUS *, + isc_db_handle *, + isc_stmt_handle *); + +ISC_STATUS ISC_EXPORT isc_dsql_describe(ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_describe_bind(ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_exec_immed2(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned short, + char *, + unsigned short, + XSQLDA *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_execute(ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_execute2(ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + XSQLDA *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned short, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_fetch(ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_finish(isc_db_handle *); + +ISC_STATUS ISC_EXPORT isc_dsql_free_statement(ISC_STATUS *, + isc_stmt_handle *, + unsigned short); + +ISC_STATUS ISC_EXPORT isc_dsql_insert(ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_prepare(ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_dsql_set_cursor_name(ISC_STATUS *, + isc_stmt_handle *, + char *, + unsigned short); + +ISC_STATUS ISC_EXPORT isc_dsql_sql_info(ISC_STATUS *, + isc_stmt_handle *, + short, + const char *, + short, + char *); + +void ISC_EXPORT isc_encode_date(void *, + ISC_QUAD *); + +void ISC_EXPORT isc_encode_sql_date(void *, + ISC_DATE *); + +void ISC_EXPORT isc_encode_sql_time(void *, + ISC_TIME *); + +void ISC_EXPORT isc_encode_timestamp(void *, + ISC_TIMESTAMP *); + +ISC_LONG ISC_EXPORT_VARARG isc_event_block(char * *, + char * *, + unsigned short, ...); + +void ISC_EXPORT isc_event_counts(ISC_ULONG *, + short, + char *, + char *); + +/* 17 May 2001 - isc_expand_dpb is DEPRECATED */ +void ISC_EXPORT_VARARG isc_expand_dpb(char * *, + short *, ...); + +int ISC_EXPORT isc_modify_dpb(char * *, + short *, + unsigned short, + char *, + short); + +ISC_LONG ISC_EXPORT isc_free(char *); + +ISC_STATUS ISC_EXPORT isc_get_segment(ISC_STATUS *, + isc_blob_handle *, + unsigned short *, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_get_slice(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + ISC_QUAD *, + short, + char *, + short, + ISC_LONG *, + ISC_LONG, + void *, + ISC_LONG *); + +ISC_STATUS ISC_EXPORT isc_interprete(char *, + ISC_STATUS * *); + +ISC_STATUS ISC_EXPORT isc_open_blob(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + isc_blob_handle *, + ISC_QUAD *); + +ISC_STATUS ISC_EXPORT isc_open_blob2(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + isc_blob_handle *, + ISC_QUAD *, + ISC_USHORT, + ISC_UCHAR *); + +ISC_STATUS ISC_EXPORT isc_prepare_transaction2(ISC_STATUS *, + isc_tr_handle *, + ISC_USHORT, + ISC_UCHAR *); + +void ISC_EXPORT isc_print_sqlerror(ISC_SHORT, + ISC_STATUS *); + +ISC_STATUS ISC_EXPORT isc_print_status(ISC_STATUS *); + +ISC_STATUS ISC_EXPORT isc_put_segment(ISC_STATUS *, + isc_blob_handle *, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_put_slice(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + ISC_QUAD *, + short, + char *, + short, + ISC_LONG *, + ISC_LONG, + void *); + +ISC_STATUS ISC_EXPORT isc_que_events(ISC_STATUS *, + isc_db_handle *, + ISC_LONG *, + short, + char *, + isc_callback, + void *); + +ISC_STATUS ISC_EXPORT isc_rollback_retaining(ISC_STATUS *, + isc_tr_handle *); + +ISC_STATUS ISC_EXPORT isc_rollback_transaction(ISC_STATUS *, + isc_tr_handle *); + +ISC_STATUS ISC_EXPORT isc_start_multiple(ISC_STATUS *, + isc_tr_handle *, + short, + void *); + +ISC_STATUS ISC_EXPORT_VARARG isc_start_transaction(ISC_STATUS *, + isc_tr_handle *, + short, ...); + +ISC_LONG ISC_EXPORT isc_sqlcode(ISC_STATUS *); + +void ISC_EXPORT isc_sql_interprete(short, + char *, + short); + +ISC_STATUS ISC_EXPORT isc_transaction_info(ISC_STATUS *, + isc_tr_handle *, + short, + char *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_transact_request(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned short, + char *, + unsigned short, + char *, + unsigned short, + char *); + +ISC_LONG ISC_EXPORT isc_vax_integer(char *, + short); + +ISC_INT64 ISC_EXPORT isc_portable_integer(unsigned char *, + short); + +/*************************************/ +/* Security Functions and structures */ +/*************************************/ + +#define sec_uid_spec 0x01 +#define sec_gid_spec 0x02 +#define sec_server_spec 0x04 +#define sec_password_spec 0x08 +#define sec_group_name_spec 0x10 +#define sec_first_name_spec 0x20 +#define sec_middle_name_spec 0x40 +#define sec_last_name_spec 0x80 +#define sec_dba_user_name_spec 0x100 +#define sec_dba_password_spec 0x200 + +#define sec_protocol_tcpip 1 +#define sec_protocol_netbeui 2 +#define sec_protocol_spx 3 /* -- Deprecated Protocol. Declaration retained for compatibility */ +#define sec_protocol_local 4 + +typedef struct { + short sec_flags; /* which fields are specified */ + int uid; /* the user's id */ + int gid; /* the user's group id */ + int protocol; /* protocol to use for connection */ + char *server; /* server to administer */ + char *user_name; /* the user's name */ + char *password; /* the user's password */ + char *group_name; /* the group name */ + char *first_name; /* the user's first name */ + char *middle_name; /* the user's middle name */ + char *last_name; /* the user's last name */ + char *dba_user_name; /* the dba user name */ + char *dba_password; /* the dba password */ +} USER_SEC_DATA; + +int ISC_EXPORT isc_add_user(ISC_STATUS *, USER_SEC_DATA *); + +int ISC_EXPORT isc_delete_user(ISC_STATUS *, USER_SEC_DATA *); + +int ISC_EXPORT isc_modify_user(ISC_STATUS *, USER_SEC_DATA *); + +/**********************************/ +/* Other OSRI functions */ +/**********************************/ + +ISC_STATUS ISC_EXPORT isc_compile_request(ISC_STATUS *, + isc_db_handle *, + isc_req_handle *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_compile_request2(ISC_STATUS *, + isc_db_handle *, + isc_req_handle *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_ddl(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_prepare_transaction(ISC_STATUS *, + isc_tr_handle *); + + +ISC_STATUS ISC_EXPORT isc_receive(ISC_STATUS *, + isc_req_handle *, + short, + short, + void *, + short); + +ISC_STATUS ISC_EXPORT isc_reconnect_transaction(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_release_request(ISC_STATUS *, + isc_req_handle *); + +ISC_STATUS ISC_EXPORT isc_request_info(ISC_STATUS *, + isc_req_handle *, + short, + short, + char *, + short, + char *); + +ISC_STATUS ISC_EXPORT isc_seek_blob(ISC_STATUS *, + isc_blob_handle *, + short, + ISC_LONG, + ISC_LONG *); + +ISC_STATUS ISC_EXPORT isc_send(ISC_STATUS *, + isc_req_handle *, + short, + short, + void *, + short); + +ISC_STATUS ISC_EXPORT isc_start_and_send(ISC_STATUS *, + isc_req_handle *, + isc_tr_handle *, + short, + short, + void *, + short); + +ISC_STATUS ISC_EXPORT isc_start_request(ISC_STATUS *, + isc_req_handle *, + isc_tr_handle *, + short); + +ISC_STATUS ISC_EXPORT isc_unwind_request(ISC_STATUS *, + isc_tr_handle *, + short); + +ISC_STATUS ISC_EXPORT isc_wait_for_event(ISC_STATUS *, + isc_db_handle *, + short, + char *, + char *); + + +/*****************************/ +/* Other Sql functions */ +/*****************************/ + +ISC_STATUS ISC_EXPORT isc_close(ISC_STATUS *, + char *); + +ISC_STATUS ISC_EXPORT isc_declare(ISC_STATUS *, + char *, + char *); + +ISC_STATUS ISC_EXPORT isc_describe(ISC_STATUS *, + char *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_describe_bind(ISC_STATUS *, + char *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_execute(ISC_STATUS *, + isc_tr_handle *, + char *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_execute_immediate(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + short *, + char *); + +ISC_STATUS ISC_EXPORT isc_fetch(ISC_STATUS *, + char *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_open(ISC_STATUS *, + isc_tr_handle *, + char *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_prepare(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + char *, + short *, + char *, + XSQLDA *); + + +/*************************************/ +/* Other Dynamic sql functions */ +/*************************************/ + +ISC_STATUS ISC_EXPORT isc_dsql_execute_m(ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_dsql_execute2_m(ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_dsql_execute_immediate_m(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *, + unsigned short, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_dsql_exec_immed3_m(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *, + unsigned short, + unsigned short, + char *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_dsql_fetch_m(ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_dsql_insert_m(ISC_STATUS *, + isc_stmt_handle *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_dsql_prepare_m(ISC_STATUS *, + isc_tr_handle *, + isc_stmt_handle *, + unsigned short, + char *, + unsigned short, + unsigned short, + char *, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_dsql_release(ISC_STATUS *, + char *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_close(ISC_STATUS *, + char *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_declare(ISC_STATUS *, + char *, + char *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_describe(ISC_STATUS *, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_describe_bind(ISC_STATUS *, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_execute(ISC_STATUS *, + isc_tr_handle *, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_execute2(ISC_STATUS *, + isc_tr_handle *, + char *, + unsigned short, + XSQLDA *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_execute_immed(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + unsigned short, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_fetch(ISC_STATUS *, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_open(ISC_STATUS *, + isc_tr_handle *, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_open2(ISC_STATUS *, + isc_tr_handle *, + char *, + unsigned short, + XSQLDA *, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_insert(ISC_STATUS *, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_prepare(ISC_STATUS *, + isc_db_handle *, + isc_tr_handle *, + char *, + unsigned short, + char *, + unsigned short, + XSQLDA *); + +ISC_STATUS ISC_EXPORT isc_embed_dsql_release(ISC_STATUS *, + char *); + + +/******************************/ +/* Other Blob functions */ +/******************************/ + +BSTREAM *ISC_EXPORT BLOB_open(isc_blob_handle, + char *, + int); + +int ISC_EXPORT BLOB_put(char, + BSTREAM *); + +int ISC_EXPORT BLOB_close(BSTREAM *); + +int ISC_EXPORT BLOB_get(BSTREAM *); + +int ISC_EXPORT BLOB_display(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *); + +int ISC_EXPORT BLOB_dump(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *); + +int ISC_EXPORT BLOB_edit(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *); + +int ISC_EXPORT BLOB_load(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *); + +int ISC_EXPORT BLOB_text_dump(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *); + +int ISC_EXPORT BLOB_text_load(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *); + +BSTREAM *ISC_EXPORT Bopen(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *); + +BSTREAM *ISC_EXPORT Bopen2(ISC_QUAD *, + isc_db_handle, + isc_tr_handle, + char *, + unsigned short); + + +/******************************/ +/* Other Misc functions */ +/******************************/ + +ISC_LONG ISC_EXPORT isc_ftof(char *, + unsigned short, + char *, + unsigned short); + +ISC_STATUS ISC_EXPORT isc_print_blr(char *, + isc_callback, + void *, + short); + +void ISC_EXPORT isc_set_debug(int); + +void ISC_EXPORT isc_qtoq(ISC_QUAD *, + ISC_QUAD *); + +void ISC_EXPORT isc_vtof(char *, + char *, + unsigned short); + +void ISC_EXPORT isc_vtov(char *, + char *, + short); + +int ISC_EXPORT isc_version(isc_db_handle *, + isc_callback, + void *); + +ISC_LONG ISC_EXPORT isc_reset_fpe(unsigned short); + + +/*****************************************/ +/* Service manager functions */ +/*****************************************/ + +#define ADD_SPB_LENGTH(p, length) {*(p)++ = (length); *(p)++ = (length) >> 8;} + +#define ADD_SPB_NUMERIC(p, data) {*(p)++ = (SCHAR) (data); *(p)++ = (SCHAR) ((data) >> 8); *(p)++ = (SCHAR) ((data) >> 16); *(p)++ = (SCHAR) ((data) >> 24);} + +ISC_STATUS ISC_EXPORT isc_service_attach(ISC_STATUS *, + unsigned short, + char *, + isc_svc_handle *, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_service_detach(ISC_STATUS *, + isc_svc_handle *); + +ISC_STATUS ISC_EXPORT isc_service_query(ISC_STATUS *, + isc_svc_handle *, + isc_resv_handle *, + unsigned short, + char *, + unsigned short, + char *, + unsigned short, + char *); + +ISC_STATUS ISC_EXPORT isc_service_start(ISC_STATUS *, + isc_svc_handle *, + isc_resv_handle *, + unsigned short, + char *); + + +/********************************/ +/* Client information functions */ +/********************************/ + +void ISC_EXPORT isc_get_client_version ( char *); +int ISC_EXPORT isc_get_client_major_version (); +int ISC_EXPORT isc_get_client_minor_version (); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + + +/***************************************************/ +/* Actions to pass to the blob filter (ctl_source) */ +/***************************************************/ + +#define isc_blob_filter_open 0 +#define isc_blob_filter_get_segment 1 +#define isc_blob_filter_close 2 +#define isc_blob_filter_create 3 +#define isc_blob_filter_put_segment 4 +#define isc_blob_filter_alloc 5 +#define isc_blob_filter_free 6 +#define isc_blob_filter_seek 7 + +/*******************/ +/* Blr definitions */ +/*******************/ + +/* + * PROGRAM: C preprocessor + * MODULE: blr.h + * DESCRIPTION: BLR constants + * + * The contents of this file are subject to the Interbase Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy + * of the License at http://www.Inprise.com/IPL.html + * + * Software distributed under the License is distributed on an + * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express + * or implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code was created by Inprise Corporation + * and its predecessors. Portions created by Inprise Corporation are + * Copyright (C) Inprise Corporation. + * + * All Rights Reserved. + * Contributor(s): ______________________________________. + * + * Claudio Valderrama: 2001.6.18: Add blr_current_role. + * 2002.09.28 Dmitry Yemanov: Reworked internal_info stuff, enhanced + * exception handling in SPs/triggers, + * implemented ROWS_AFFECTED system variable + * 2002.10.21 Nickolay Samofatov: Added support for explicit pessimistic locks + * 2002.10.29 Nickolay Samofatov: Added support for savepoints + */ + +#ifndef _JRD_BLR_H_ +#define _JRD_BLR_H_ + +/* WARNING: if you add a new BLR representing a data type, and the value + * is greater than the numerically greatest value which now + * represents a data type, you must change the define for + * DTYPE_BLR_MAX in jrd/align.h, and add the necessary entries + * to all the arrays in that file. + */ + +#define blr_text (unsigned char)14 +#define blr_text2 (unsigned char)15 /* added in 3.2 JPN */ +#define blr_short (unsigned char)7 +#define blr_long (unsigned char)8 +#define blr_quad (unsigned char)9 +#define blr_float (unsigned char)10 +#define blr_double (unsigned char)27 +#define blr_d_float (unsigned char)11 +#define blr_timestamp (unsigned char)35 +#define blr_varying (unsigned char)37 +#define blr_varying2 (unsigned char)38 /* added in 3.2 JPN */ +#define blr_blob (unsigned short)261 +#define blr_cstring (unsigned char)40 +#define blr_cstring2 (unsigned char)41 /* added in 3.2 JPN */ +#define blr_blob_id (unsigned char)45 /* added from gds.h */ +#define blr_sql_date (unsigned char)12 +#define blr_sql_time (unsigned char)13 +#define blr_int64 (unsigned char)16 + +/* Historical alias for pre V6 applications */ +#define blr_date blr_timestamp + +#define blr_inner (unsigned char)0 +#define blr_left (unsigned char)1 +#define blr_right (unsigned char)2 +#define blr_full (unsigned char)3 + +#define blr_gds_code (unsigned char)0 +#define blr_sql_code (unsigned char)1 +#define blr_exception (unsigned char)2 +#define blr_trigger_code (unsigned char)3 +#define blr_default_code (unsigned char)4 +#define blr_raise (unsigned char)5 +#define blr_exception_msg (unsigned char)6 + +#define blr_version4 (unsigned char)4 +#define blr_version5 (unsigned char)5 +#define blr_eoc (unsigned char)76 +#define blr_end (unsigned char)255 /* note: defined as -1 in gds.h */ + +#define blr_assignment (unsigned char)1 +#define blr_begin (unsigned char)2 +#define blr_dcl_variable (unsigned char)3 /* added from gds.h */ +#define blr_message (unsigned char)4 +#define blr_erase (unsigned char)5 +#define blr_fetch (unsigned char)6 +#define blr_for (unsigned char)7 +#define blr_if (unsigned char)8 +#define blr_loop (unsigned char)9 +#define blr_modify (unsigned char)10 +#define blr_handler (unsigned char)11 +#define blr_receive (unsigned char)12 +#define blr_select (unsigned char)13 +#define blr_send (unsigned char)14 +#define blr_store (unsigned char)15 +#define blr_label (unsigned char)17 +#define blr_leave (unsigned char)18 +#define blr_store2 (unsigned char)19 +#define blr_post (unsigned char)20 +#define blr_literal (unsigned char)21 +#define blr_dbkey (unsigned char)22 +#define blr_field (unsigned char)23 +#define blr_fid (unsigned char)24 +#define blr_parameter (unsigned char)25 +#define blr_variable (unsigned char)26 +#define blr_average (unsigned char)27 +#define blr_count (unsigned char)28 +#define blr_maximum (unsigned char)29 +#define blr_minimum (unsigned char)30 +#define blr_total (unsigned char)31 +/* count 2 +#define blr_count2 32 +*/ +#define blr_add (unsigned char)34 +#define blr_subtract (unsigned char)35 +#define blr_multiply (unsigned char)36 +#define blr_divide (unsigned char)37 +#define blr_negate (unsigned char)38 +#define blr_concatenate (unsigned char)39 +#define blr_substring (unsigned char)40 +#define blr_parameter2 (unsigned char)41 +#define blr_from (unsigned char)42 +#define blr_via (unsigned char)43 +#define blr_parameter2_old (unsigned char)44 /* Confusion */ +#define blr_user_name (unsigned char)44 /* added from gds.h */ +#define blr_null (unsigned char)45 + +#define blr_eql (unsigned char)47 +#define blr_neq (unsigned char)48 +#define blr_gtr (unsigned char)49 +#define blr_geq (unsigned char)50 +#define blr_lss (unsigned char)51 +#define blr_leq (unsigned char)52 +#define blr_containing (unsigned char)53 +#define blr_matching (unsigned char)54 +#define blr_starting (unsigned char)55 +#define blr_between (unsigned char)56 +#define blr_or (unsigned char)57 +#define blr_and (unsigned char)58 +#define blr_not (unsigned char)59 +#define blr_any (unsigned char)60 +#define blr_missing (unsigned char)61 +#define blr_unique (unsigned char)62 +#define blr_like (unsigned char)63 + +#define blr_stream (unsigned char)65 /* added from gds.h */ +#define blr_set_index (unsigned char)66 /* added from gds.h */ + +#define blr_rse (unsigned char)67 +#define blr_first (unsigned char)68 +#define blr_project (unsigned char)69 +#define blr_sort (unsigned char)70 +#define blr_boolean (unsigned char)71 +#define blr_ascending (unsigned char)72 +#define blr_descending (unsigned char)73 +#define blr_relation (unsigned char)74 +#define blr_rid (unsigned char)75 +#define blr_union (unsigned char)76 +#define blr_map (unsigned char)77 +#define blr_group_by (unsigned char)78 +#define blr_aggregate (unsigned char)79 +#define blr_join_type (unsigned char)80 + +#define blr_agg_count (unsigned char)83 +#define blr_agg_max (unsigned char)84 +#define blr_agg_min (unsigned char)85 +#define blr_agg_total (unsigned char)86 +#define blr_agg_average (unsigned char)87 +#define blr_parameter3 (unsigned char)88 /* same as Rdb definition */ +#define blr_run_max (unsigned char)89 +#define blr_run_min (unsigned char)90 +#define blr_run_total (unsigned char)91 +#define blr_run_average (unsigned char)92 +#define blr_agg_count2 (unsigned char)93 +#define blr_agg_count_distinct (unsigned char)94 +#define blr_agg_total_distinct (unsigned char)95 +#define blr_agg_average_distinct (unsigned char)96 + +#define blr_function (unsigned char)100 +#define blr_gen_id (unsigned char)101 +#define blr_prot_mask (unsigned char)102 +#define blr_upcase (unsigned char)103 +#define blr_lock_state (unsigned char)104 +#define blr_value_if (unsigned char)105 +#define blr_matching2 (unsigned char)106 +#define blr_index (unsigned char)107 +#define blr_ansi_like (unsigned char)108 +#define blr_bookmark (unsigned char)109 +#define blr_crack (unsigned char)110 +#define blr_force_crack (unsigned char)111 +#define blr_seek (unsigned char)112 +#define blr_find (unsigned char)113 + +/* these indicate directions for blr_seek and blr_find */ + +#define blr_continue (unsigned char)0 +#define blr_forward (unsigned char)1 +#define blr_backward (unsigned char)2 +#define blr_bof_forward (unsigned char)3 +#define blr_eof_backward (unsigned char)4 + +#define blr_lock_relation (unsigned char)114 +#define blr_lock_record (unsigned char)115 +#define blr_set_bookmark (unsigned char)116 +#define blr_get_bookmark (unsigned char)117 + +#define blr_run_count (unsigned char)118 /* changed from 88 to avoid conflict with blr_parameter3 */ +#define blr_rs_stream (unsigned char)119 +#define blr_exec_proc (unsigned char)120 +#define blr_begin_range (unsigned char)121 +#define blr_end_range (unsigned char)122 +#define blr_delete_range (unsigned char)123 +#define blr_procedure (unsigned char)124 +#define blr_pid (unsigned char)125 +#define blr_exec_pid (unsigned char)126 +#define blr_singular (unsigned char)127 +#define blr_abort (unsigned char)128 +#define blr_block (unsigned char)129 +#define blr_error_handler (unsigned char)130 + +#define blr_cast (unsigned char)131 +#define blr_release_lock (unsigned char)132 +#define blr_release_locks (unsigned char)133 +#define blr_start_savepoint (unsigned char)134 +#define blr_end_savepoint (unsigned char)135 +#define blr_find_dbkey (unsigned char)136 +#define blr_range_relation (unsigned char)137 +#define blr_delete_ranges (unsigned char)138 + +#define blr_plan (unsigned char)139 /* access plan items */ +#define blr_merge (unsigned char)140 +#define blr_join (unsigned char)141 +#define blr_sequential (unsigned char)142 +#define blr_navigational (unsigned char)143 +#define blr_indices (unsigned char)144 +#define blr_retrieve (unsigned char)145 + +#define blr_relation2 (unsigned char)146 +#define blr_rid2 (unsigned char)147 +#define blr_reset_stream (unsigned char)148 +#define blr_release_bookmark (unsigned char)149 + +#define blr_set_generator (unsigned char)150 + +#define blr_ansi_any (unsigned char)151 /* required for NULL handling */ +#define blr_exists (unsigned char)152 /* required for NULL handling */ +#define blr_cardinality (unsigned char)153 + +#define blr_record_version (unsigned char)154 /* get tid of record */ +#define blr_stall (unsigned char)155 /* fake server stall */ + +#define blr_seek_no_warn (unsigned char)156 +#define blr_find_dbkey_version (unsigned char)157 /* find dbkey with record version */ +#define blr_ansi_all (unsigned char)158 /* required for NULL handling */ + +#define blr_extract (unsigned char)159 + +/* sub parameters for blr_extract */ + +#define blr_extract_year (unsigned char)0 +#define blr_extract_month (unsigned char)1 +#define blr_extract_day (unsigned char)2 +#define blr_extract_hour (unsigned char)3 +#define blr_extract_minute (unsigned char)4 +#define blr_extract_second (unsigned char)5 +#define blr_extract_weekday (unsigned char)6 +#define blr_extract_yearday (unsigned char)7 + +#define blr_current_date (unsigned char)160 +#define blr_current_timestamp (unsigned char)161 +#define blr_current_time (unsigned char)162 + +/* FB 1.0 specific BLR */ + +#define blr_current_role (unsigned char)174 +#define blr_skip (unsigned char)175 + +/* FB 1.5 specific BLR */ + +#define blr_exec_sql (unsigned char)176 +#define blr_internal_info (unsigned char)177 +#define blr_nullsfirst (unsigned char)178 +#define blr_writelock (unsigned char)179 +#define blr_nullslast (unsigned char)180 + +/* These codes reuse BLR code space */ + +#define blr_post_arg (unsigned char)163 +#define blr_exec_into (unsigned char)164 +#define blr_user_savepoint (unsigned char)165 + +/* These codes are actions for user-defined savepoints */ + +#define blr_savepoint_set (unsigned char)0 +#define blr_savepoint_release (unsigned char)1 +#define blr_savepoint_undo (unsigned char)2 +#define blr_savepoint_release_single (unsigned char)3 + +#endif /* _JRD_BLR_H_ */ + + +/**********************************/ +/* Database parameter block stuff */ +/**********************************/ + +#define isc_dpb_version1 1 +#define isc_dpb_cdd_pathname 1 +#define isc_dpb_allocation 2 +#define isc_dpb_journal 3 +#define isc_dpb_page_size 4 +#define isc_dpb_num_buffers 5 +#define isc_dpb_buffer_length 6 +#define isc_dpb_debug 7 +#define isc_dpb_garbage_collect 8 +#define isc_dpb_verify 9 +#define isc_dpb_sweep 10 +#define isc_dpb_enable_journal 11 +#define isc_dpb_disable_journal 12 +#define isc_dpb_dbkey_scope 13 +#define isc_dpb_number_of_users 14 +#define isc_dpb_trace 15 +#define isc_dpb_no_garbage_collect 16 +#define isc_dpb_damaged 17 +#define isc_dpb_license 18 +#define isc_dpb_sys_user_name 19 +#define isc_dpb_encrypt_key 20 +#define isc_dpb_activate_shadow 21 +#define isc_dpb_sweep_interval 22 +#define isc_dpb_delete_shadow 23 +#define isc_dpb_force_write 24 +#define isc_dpb_begin_log 25 +#define isc_dpb_quit_log 26 +#define isc_dpb_no_reserve 27 +#define isc_dpb_user_name 28 +#define isc_dpb_password 29 +#define isc_dpb_password_enc 30 +#define isc_dpb_sys_user_name_enc 31 +#define isc_dpb_interp 32 +#define isc_dpb_online_dump 33 +#define isc_dpb_old_file_size 34 +#define isc_dpb_old_num_files 35 +#define isc_dpb_old_file 36 +#define isc_dpb_old_start_page 37 +#define isc_dpb_old_start_seqno 38 +#define isc_dpb_old_start_file 39 +#define isc_dpb_drop_walfile 40 +#define isc_dpb_old_dump_id 41 +#define isc_dpb_wal_backup_dir 42 +#define isc_dpb_wal_chkptlen 43 +#define isc_dpb_wal_numbufs 44 +#define isc_dpb_wal_bufsize 45 +#define isc_dpb_wal_grp_cmt_wait 46 +#define isc_dpb_lc_messages 47 +#define isc_dpb_lc_ctype 48 +#define isc_dpb_cache_manager 49 +#define isc_dpb_shutdown 50 +#define isc_dpb_online 51 +#define isc_dpb_shutdown_delay 52 +#define isc_dpb_reserved 53 +#define isc_dpb_overwrite 54 +#define isc_dpb_sec_attach 55 +#define isc_dpb_disable_wal 56 +#define isc_dpb_connect_timeout 57 +#define isc_dpb_dummy_packet_interval 58 +#define isc_dpb_gbak_attach 59 +#define isc_dpb_sql_role_name 60 +#define isc_dpb_set_page_buffers 61 +#define isc_dpb_working_directory 62 +#define isc_dpb_sql_dialect 63 +#define isc_dpb_set_db_readonly 64 +#define isc_dpb_set_db_sql_dialect 65 +#define isc_dpb_gfix_attach 66 +#define isc_dpb_gstat_attach 67 +#define isc_dpb_set_db_charset 68 + +/*********************************/ +/* isc_dpb_verify specific flags */ +/*********************************/ + +#define isc_dpb_pages 1 +#define isc_dpb_records 2 +#define isc_dpb_indices 4 +#define isc_dpb_transactions 8 +#define isc_dpb_no_update 16 +#define isc_dpb_repair 32 +#define isc_dpb_ignore 64 + +/***********************************/ +/* isc_dpb_shutdown specific flags */ +/***********************************/ + +#define isc_dpb_shut_cache 1 +#define isc_dpb_shut_attachment 2 +#define isc_dpb_shut_transaction 4 +#define isc_dpb_shut_force 8 + +/**************************************/ +/* Bit assignments in RDB$SYSTEM_FLAG */ +/**************************************/ + +#define RDB_system 1 +#define RDB_id_assigned 2 + + +/*************************************/ +/* Transaction parameter block stuff */ +/*************************************/ + +#define isc_tpb_version1 1 +#define isc_tpb_version3 3 +#define isc_tpb_consistency 1 +#define isc_tpb_concurrency 2 +#define isc_tpb_shared 3 +#define isc_tpb_protected 4 +#define isc_tpb_exclusive 5 +#define isc_tpb_wait 6 +#define isc_tpb_nowait 7 +#define isc_tpb_read 8 +#define isc_tpb_write 9 +#define isc_tpb_lock_read 10 +#define isc_tpb_lock_write 11 +#define isc_tpb_verb_time 12 +#define isc_tpb_commit_time 13 +#define isc_tpb_ignore_limbo 14 +#define isc_tpb_read_committed 15 +#define isc_tpb_autocommit 16 +#define isc_tpb_rec_version 17 +#define isc_tpb_no_rec_version 18 +#define isc_tpb_restart_requests 19 +#define isc_tpb_no_auto_undo 20 + + +/************************/ +/* Blob Parameter Block */ +/************************/ + +#define isc_bpb_version1 1 +#define isc_bpb_source_type 1 +#define isc_bpb_target_type 2 +#define isc_bpb_type 3 +#define isc_bpb_source_interp 4 +#define isc_bpb_target_interp 5 +#define isc_bpb_filter_parameter 6 + +#define isc_bpb_type_segmented 0 +#define isc_bpb_type_stream 1 + + +/*********************************/ +/* Service parameter block stuff */ +/*********************************/ + +#define isc_spb_version1 1 +#define isc_spb_current_version 2 +#define isc_spb_version isc_spb_current_version +#define isc_spb_user_name isc_dpb_user_name +#define isc_spb_sys_user_name isc_dpb_sys_user_name +#define isc_spb_sys_user_name_enc isc_dpb_sys_user_name_enc +#define isc_spb_password isc_dpb_password +#define isc_spb_password_enc isc_dpb_password_enc +#define isc_spb_command_line 105 +#define isc_spb_dbname 106 +#define isc_spb_verbose 107 +#define isc_spb_options 108 + +#define isc_spb_connect_timeout isc_dpb_connect_timeout +#define isc_spb_dummy_packet_interval isc_dpb_dummy_packet_interval +#define isc_spb_sql_role_name isc_dpb_sql_role_name + + +/*********************************/ +/* Information call declarations */ +/*********************************/ + +/****************************/ +/* Common, structural codes */ +/****************************/ + +#define isc_info_end 1 +#define isc_info_truncated 2 +#define isc_info_error 3 +#define isc_info_data_not_ready 4 +#define isc_info_flag_end 127 + +/******************************/ +/* Database information items */ +/******************************/ + +enum db_info_types + { + isc_info_db_id = 4, + isc_info_reads = 5, + isc_info_writes = 6, + isc_info_fetches = 7, + isc_info_marks = 8, + + isc_info_implementation = 11, + isc_info_isc_version = 12, + isc_info_base_level = 13, + isc_info_page_size = 14, + isc_info_num_buffers = 15, + isc_info_limbo = 16, + isc_info_current_memory = 17, + isc_info_max_memory = 18, + isc_info_window_turns = 19, + isc_info_license = 20, + + isc_info_allocation = 21, + isc_info_attachment_id = 22, + isc_info_read_seq_count = 23, + isc_info_read_idx_count = 24, + isc_info_insert_count = 25, + isc_info_update_count = 26, + isc_info_delete_count = 27, + isc_info_backout_count = 28, + isc_info_purge_count = 29, + isc_info_expunge_count = 30, + + isc_info_sweep_interval = 31, + isc_info_ods_version = 32, + isc_info_ods_minor_version = 33, + isc_info_no_reserve = 34, + isc_info_logfile = 35, + isc_info_cur_logfile_name = 36, + isc_info_cur_log_part_offset = 37, + isc_info_num_wal_buffers = 38, + isc_info_wal_buffer_size = 39, + isc_info_wal_ckpt_length = 40, + + isc_info_wal_cur_ckpt_interval = 41, + isc_info_wal_prv_ckpt_fname = 42, + isc_info_wal_prv_ckpt_poffset = 43, + isc_info_wal_recv_ckpt_fname = 44, + isc_info_wal_recv_ckpt_poffset = 45, + isc_info_wal_grpc_wait_usecs = 47, + isc_info_wal_num_io = 48, + isc_info_wal_avg_io_size = 49, + isc_info_wal_num_commits = 50, + + isc_info_wal_avg_grpc_size = 51, + isc_info_forced_writes = 52, + isc_info_user_names = 53, + isc_info_page_errors = 54, + isc_info_record_errors = 55, + isc_info_bpage_errors = 56, + isc_info_dpage_errors = 57, + isc_info_ipage_errors = 58, + isc_info_ppage_errors = 59, + isc_info_tpage_errors = 60, + + isc_info_set_page_buffers = 61, + isc_info_db_sql_dialect = 62, + isc_info_db_read_only = 63, + isc_info_db_size_in_pages = 64, + + /* Values 65 -100 unused to avoid conflict with InterBase */ + + frb_info_att_charset = 101, + isc_info_db_class = 102, + isc_info_firebird_version = 103, + isc_info_oldest_transaction = 104, + isc_info_oldest_active = 105, + isc_info_oldest_snapshot = 106, + isc_info_next_transaction = 107, + isc_info_db_provider = 108, + isc_info_active_transactions = 109, + + isc_info_db_last_value /* Leave this LAST! */ + }; + +#define isc_info_version isc_info_isc_version + + +/**************************************/ +/* Database information return values */ +/**************************************/ + +enum info_db_implementations + { + isc_info_db_impl_rdb_vms = 1, + isc_info_db_impl_rdb_eln = 2, + isc_info_db_impl_rdb_eln_dev = 3, + isc_info_db_impl_rdb_vms_y = 4, + isc_info_db_impl_rdb_eln_y = 5, + isc_info_db_impl_jri = 6, + isc_info_db_impl_jsv = 7, + + isc_info_db_impl_isc_apl_68K = 25, + isc_info_db_impl_isc_vax_ultr = 26, + isc_info_db_impl_isc_vms = 27, + isc_info_db_impl_isc_sun_68k = 28, + isc_info_db_impl_isc_os2 = 29, + isc_info_db_impl_isc_sun4 = 30, /* 30 */ + + isc_info_db_impl_isc_hp_ux = 31, + isc_info_db_impl_isc_sun_386i = 32, + isc_info_db_impl_isc_vms_orcl = 33, + isc_info_db_impl_isc_mac_aux = 34, + isc_info_db_impl_isc_rt_aix = 35, + isc_info_db_impl_isc_mips_ult = 36, + isc_info_db_impl_isc_xenix = 37, + isc_info_db_impl_isc_dg = 38, + isc_info_db_impl_isc_hp_mpexl = 39, + isc_info_db_impl_isc_hp_ux68K = 40, /* 40 */ + + isc_info_db_impl_isc_sgi = 41, + isc_info_db_impl_isc_sco_unix = 42, + isc_info_db_impl_isc_cray = 43, + isc_info_db_impl_isc_imp = 44, + isc_info_db_impl_isc_delta = 45, + isc_info_db_impl_isc_next = 46, + isc_info_db_impl_isc_dos = 47, + isc_info_db_impl_m88K = 48, + isc_info_db_impl_unixware = 49, + isc_info_db_impl_isc_winnt_x86 = 50, + + isc_info_db_impl_isc_epson = 51, + isc_info_db_impl_alpha_osf = 52, + isc_info_db_impl_alpha_vms = 53, + isc_info_db_impl_netware_386 = 54, + isc_info_db_impl_win_only = 55, + isc_info_db_impl_ncr_3000 = 56, + isc_info_db_impl_winnt_ppc = 57, + isc_info_db_impl_dg_x86 = 58, + isc_info_db_impl_sco_ev = 59, + isc_info_db_impl_i386 = 60, + + isc_info_db_impl_freebsd = 61, + isc_info_db_impl_netbsd = 62, + isc_info_db_impl_darwin = 63, + isc_info_db_impl_sinixz = 64, + + isc_info_db_impl_linux_sparc = 65, + isc_info_db_impl_linux_amd64 = 66, + + isc_info_db_impl_last_value /* Leave this LAST! */ + }; + +#define isc_info_db_impl_isc_a isc_info_db_impl_isc_apl_68K +#define isc_info_db_impl_isc_u isc_info_db_impl_isc_vax_ultr +#define isc_info_db_impl_isc_v isc_info_db_impl_isc_vms +#define isc_info_db_impl_isc_s isc_info_db_impl_isc_sun_68k + + +enum info_db_class + { + isc_info_db_class_access = 1, + isc_info_db_class_y_valve = 2, + isc_info_db_class_rem_int = 3, + isc_info_db_class_rem_srvr = 4, + isc_info_db_class_pipe_int = 7, + isc_info_db_class_pipe_srvr = 8, + isc_info_db_class_sam_int = 9, + isc_info_db_class_sam_srvr = 10, + isc_info_db_class_gateway = 11, + isc_info_db_class_cache = 12, + isc_info_db_class_classic_access = 13, + isc_info_db_class_server_access = 14, + + isc_info_db_class_last_value /* Leave this LAST! */ + }; + +enum info_db_provider + { + isc_info_db_code_rdb_eln = 1, + isc_info_db_code_rdb_vms = 2, + isc_info_db_code_interbase = 3, + isc_info_db_code_firebird = 4, + + isc_info_db_code_last_value /* Leave this LAST! */ + }; + + +/*****************************/ +/* Request information items */ +/*****************************/ + +#define isc_info_number_messages 4 +#define isc_info_max_message 5 +#define isc_info_max_send 6 +#define isc_info_max_receive 7 +#define isc_info_state 8 +#define isc_info_message_number 9 +#define isc_info_message_size 10 +#define isc_info_request_cost 11 +#define isc_info_access_path 12 +#define isc_info_req_select_count 13 +#define isc_info_req_insert_count 14 +#define isc_info_req_update_count 15 +#define isc_info_req_delete_count 16 + + +/*********************/ +/* Access path items */ +/*********************/ + +#define isc_info_rsb_end 0 +#define isc_info_rsb_begin 1 +#define isc_info_rsb_type 2 +#define isc_info_rsb_relation 3 +#define isc_info_rsb_plan 4 + +/*************/ +/* Rsb types */ +/*************/ + +#define isc_info_rsb_unknown 1 +#define isc_info_rsb_indexed 2 +#define isc_info_rsb_navigate 3 +#define isc_info_rsb_sequential 4 +#define isc_info_rsb_cross 5 +#define isc_info_rsb_sort 6 +#define isc_info_rsb_first 7 +#define isc_info_rsb_boolean 8 +#define isc_info_rsb_union 9 +#define isc_info_rsb_aggregate 10 +#define isc_info_rsb_merge 11 +#define isc_info_rsb_ext_sequential 12 +#define isc_info_rsb_ext_indexed 13 +#define isc_info_rsb_ext_dbkey 14 +#define isc_info_rsb_left_cross 15 +#define isc_info_rsb_select 16 +#define isc_info_rsb_sql_join 17 +#define isc_info_rsb_simulate 18 +#define isc_info_rsb_sim_cross 19 +#define isc_info_rsb_once 20 +#define isc_info_rsb_procedure 21 + +/**********************/ +/* Bitmap expressions */ +/**********************/ + +#define isc_info_rsb_and 1 +#define isc_info_rsb_or 2 +#define isc_info_rsb_dbkey 3 +#define isc_info_rsb_index 4 + +#define isc_info_req_active 2 +#define isc_info_req_inactive 3 +#define isc_info_req_send 4 +#define isc_info_req_receive 5 +#define isc_info_req_select 6 +#define isc_info_req_sql_stall 7 + +/**************************/ +/* Blob information items */ +/**************************/ + +#define isc_info_blob_num_segments 4 +#define isc_info_blob_max_segment 5 +#define isc_info_blob_total_length 6 +#define isc_info_blob_type 7 + +/*********************************/ +/* Transaction information items */ +/*********************************/ + +#define isc_info_tra_id 4 + +/***************************** + * Service action items * + *****************************/ + +#define isc_action_svc_backup 1 /* Starts database backup process on the server */ +#define isc_action_svc_restore 2 /* Starts database restore process on the server */ +#define isc_action_svc_repair 3 /* Starts database repair process on the server */ +#define isc_action_svc_add_user 4 /* Adds a new user to the security database */ +#define isc_action_svc_delete_user 5 /* Deletes a user record from the security database */ +#define isc_action_svc_modify_user 6 /* Modifies a user record in the security database */ +#define isc_action_svc_display_user 7 /* Displays a user record from the security database */ +#define isc_action_svc_properties 8 /* Sets database properties */ +#define isc_action_svc_add_license 9 /* Adds a license to the license file */ +#define isc_action_svc_remove_license 10 /* Removes a license from the license file */ +#define isc_action_svc_db_stats 11 /* Retrieves database statistics */ +#define isc_action_svc_get_ib_log 12 /* Retrieves the InterBase log file from the server */ + +/***************************** + * Service information items * + *****************************/ + +#define isc_info_svc_svr_db_info 50 /* Retrieves the number of attachments and databases */ +#define isc_info_svc_get_license 51 /* Retrieves all license keys and IDs from the license file */ +#define isc_info_svc_get_license_mask 52 /* Retrieves a bitmask representing licensed options on the server */ +#define isc_info_svc_get_config 53 /* Retrieves the parameters and values for IB_CONFIG */ +#define isc_info_svc_version 54 /* Retrieves the version of the services manager */ +#define isc_info_svc_server_version 55 /* Retrieves the version of the InterBase server */ +#define isc_info_svc_implementation 56 /* Retrieves the implementation of the InterBase server */ +#define isc_info_svc_capabilities 57 /* Retrieves a bitmask representing the server's capabilities */ +#define isc_info_svc_user_dbpath 58 /* Retrieves the path to the security database in use by the server */ +#define isc_info_svc_get_env 59 /* Retrieves the setting of $INTERBASE */ +#define isc_info_svc_get_env_lock 60 /* Retrieves the setting of $INTERBASE_LCK */ +#define isc_info_svc_get_env_msg 61 /* Retrieves the setting of $INTERBASE_MSG */ +#define isc_info_svc_line 62 /* Retrieves 1 line of service output per call */ +#define isc_info_svc_to_eof 63 /* Retrieves as much of the server output as will fit in the supplied buffer */ +#define isc_info_svc_timeout 64 /* Sets / signifies a timeout value for reading service information */ +#define isc_info_svc_get_licensed_users 65 /* Retrieves the number of users licensed for accessing the server */ +#define isc_info_svc_limbo_trans 66 /* Retrieve the limbo transactions */ +#define isc_info_svc_running 67 /* Checks to see if a service is running on an attachment */ +#define isc_info_svc_get_users 68 /* Returns the user information from isc_action_svc_display_users */ + +/****************************************************** + * Parameters for isc_action_{add|delete|modify)_user * + ******************************************************/ + +#define isc_spb_sec_userid 5 +#define isc_spb_sec_groupid 6 +#define isc_spb_sec_username 7 +#define isc_spb_sec_password 8 +#define isc_spb_sec_groupname 9 +#define isc_spb_sec_firstname 10 +#define isc_spb_sec_middlename 11 +#define isc_spb_sec_lastname 12 + +/******************************************************* + * Parameters for isc_action_svc_(add|remove)_license, * + * isc_info_svc_get_license * + *******************************************************/ + +#define isc_spb_lic_key 5 +#define isc_spb_lic_id 6 +#define isc_spb_lic_desc 7 + + +/***************************************** + * Parameters for isc_action_svc_backup * + *****************************************/ + +#define isc_spb_bkp_file 5 +#define isc_spb_bkp_factor 6 +#define isc_spb_bkp_length 7 +#define isc_spb_bkp_ignore_checksums 0x01 +#define isc_spb_bkp_ignore_limbo 0x02 +#define isc_spb_bkp_metadata_only 0x04 +#define isc_spb_bkp_no_garbage_collect 0x08 +#define isc_spb_bkp_old_descriptions 0x10 +#define isc_spb_bkp_non_transportable 0x20 +#define isc_spb_bkp_convert 0x40 +#define isc_spb_bkp_expand 0x80 + +/******************************************** + * Parameters for isc_action_svc_properties * + ********************************************/ + +#define isc_spb_prp_page_buffers 5 +#define isc_spb_prp_sweep_interval 6 +#define isc_spb_prp_shutdown_db 7 +#define isc_spb_prp_deny_new_attachments 9 +#define isc_spb_prp_deny_new_transactions 10 +#define isc_spb_prp_reserve_space 11 +#define isc_spb_prp_write_mode 12 +#define isc_spb_prp_access_mode 13 +#define isc_spb_prp_set_sql_dialect 14 +#define isc_spb_prp_activate 0x0100 +#define isc_spb_prp_db_online 0x0200 + +/******************************************** + * Parameters for isc_spb_prp_reserve_space * + ********************************************/ + +#define isc_spb_prp_res_use_full 35 +#define isc_spb_prp_res 36 + +/****************************************** + * Parameters for isc_spb_prp_write_mode * + ******************************************/ + +#define isc_spb_prp_wm_async 37 +#define isc_spb_prp_wm_sync 38 + +/****************************************** + * Parameters for isc_spb_prp_access_mode * + ******************************************/ + +#define isc_spb_prp_am_readonly 39 +#define isc_spb_prp_am_readwrite 40 + +/***************************************** + * Parameters for isc_action_svc_repair * + *****************************************/ + +#define isc_spb_rpr_commit_trans 15 +#define isc_spb_rpr_rollback_trans 34 +#define isc_spb_rpr_recover_two_phase 17 +#define isc_spb_tra_id 18 +#define isc_spb_single_tra_id 19 +#define isc_spb_multi_tra_id 20 +#define isc_spb_tra_state 21 +#define isc_spb_tra_state_limbo 22 +#define isc_spb_tra_state_commit 23 +#define isc_spb_tra_state_rollback 24 +#define isc_spb_tra_state_unknown 25 +#define isc_spb_tra_host_site 26 +#define isc_spb_tra_remote_site 27 +#define isc_spb_tra_db_path 28 +#define isc_spb_tra_advise 29 +#define isc_spb_tra_advise_commit 30 +#define isc_spb_tra_advise_rollback 31 +#define isc_spb_tra_advise_unknown 33 + +#define isc_spb_rpr_validate_db 0x01 +#define isc_spb_rpr_sweep_db 0x02 +#define isc_spb_rpr_mend_db 0x04 +#define isc_spb_rpr_list_limbo_trans 0x08 +#define isc_spb_rpr_check_db 0x10 +#define isc_spb_rpr_ignore_checksum 0x20 +#define isc_spb_rpr_kill_shadows 0x40 +#define isc_spb_rpr_full 0x80 + +/***************************************** + * Parameters for isc_action_svc_restore * + *****************************************/ + +#define isc_spb_res_buffers 9 +#define isc_spb_res_page_size 10 +#define isc_spb_res_length 11 +#define isc_spb_res_access_mode 12 +#define isc_spb_res_deactivate_idx 0x0100 +#define isc_spb_res_no_shadow 0x0200 +#define isc_spb_res_no_validity 0x0400 +#define isc_spb_res_one_at_a_time 0x0800 +#define isc_spb_res_replace 0x1000 +#define isc_spb_res_create 0x2000 +#define isc_spb_res_use_all_space 0x4000 + +/****************************************** + * Parameters for isc_spb_res_access_mode * + ******************************************/ + +#define isc_spb_res_am_readonly isc_spb_prp_am_readonly +#define isc_spb_res_am_readwrite isc_spb_prp_am_readwrite + +/******************************************* + * Parameters for isc_info_svc_svr_db_info * + *******************************************/ + +#define isc_spb_num_att 5 +#define isc_spb_num_db 6 + +/***************************************** + * Parameters for isc_info_svc_db_stats * + *****************************************/ + +#define isc_spb_sts_data_pages 0x01 +#define isc_spb_sts_db_log 0x02 +#define isc_spb_sts_hdr_pages 0x04 +#define isc_spb_sts_idx_pages 0x08 +#define isc_spb_sts_sys_relations 0x10 +#define isc_spb_sts_record_versions 0x20 +#define isc_spb_sts_table 0x40 + +/*************************/ +/* SQL information items */ +/*************************/ + +#define isc_info_sql_select 4 +#define isc_info_sql_bind 5 +#define isc_info_sql_num_variables 6 +#define isc_info_sql_describe_vars 7 +#define isc_info_sql_describe_end 8 +#define isc_info_sql_sqlda_seq 9 +#define isc_info_sql_message_seq 10 +#define isc_info_sql_type 11 +#define isc_info_sql_sub_type 12 +#define isc_info_sql_scale 13 +#define isc_info_sql_length 14 +#define isc_info_sql_null_ind 15 +#define isc_info_sql_field 16 +#define isc_info_sql_relation 17 +#define isc_info_sql_owner 18 +#define isc_info_sql_alias 19 +#define isc_info_sql_sqlda_start 20 +#define isc_info_sql_stmt_type 21 +#define isc_info_sql_get_plan 22 +#define isc_info_sql_records 23 +#define isc_info_sql_batch_fetch 24 + +/*********************************/ +/* SQL information return values */ +/*********************************/ + +#define isc_info_sql_stmt_select 1 +#define isc_info_sql_stmt_insert 2 +#define isc_info_sql_stmt_update 3 +#define isc_info_sql_stmt_delete 4 +#define isc_info_sql_stmt_ddl 5 +#define isc_info_sql_stmt_get_segment 6 +#define isc_info_sql_stmt_put_segment 7 +#define isc_info_sql_stmt_exec_procedure 8 +#define isc_info_sql_stmt_start_trans 9 +#define isc_info_sql_stmt_commit 10 +#define isc_info_sql_stmt_rollback 11 +#define isc_info_sql_stmt_select_for_upd 12 +#define isc_info_sql_stmt_set_generator 13 +#define isc_info_sql_stmt_savepoint 14 + + +/***********************************/ +/* Server configuration key values */ +/***********************************/ + +/* Not available in Firebird 1.5 */ + + +/**********************************************/ +/* Dynamic Data Definition Language operators */ +/**********************************************/ + +/******************/ +/* Version number */ +/******************/ + +#define isc_dyn_version_1 1 +#define isc_dyn_eoc 255 + +/******************************/ +/* Operations (may be nested) */ +/******************************/ + +#define isc_dyn_begin 2 +#define isc_dyn_end 3 +#define isc_dyn_if 4 +#define isc_dyn_def_database 5 +#define isc_dyn_def_global_fld 6 +#define isc_dyn_def_local_fld 7 +#define isc_dyn_def_idx 8 +#define isc_dyn_def_rel 9 +#define isc_dyn_def_sql_fld 10 +#define isc_dyn_def_view 12 +#define isc_dyn_def_trigger 15 +#define isc_dyn_def_security_class 120 +#define isc_dyn_def_dimension 140 +#define isc_dyn_def_generator 24 +#define isc_dyn_def_function 25 +#define isc_dyn_def_filter 26 +#define isc_dyn_def_function_arg 27 +#define isc_dyn_def_shadow 34 +#define isc_dyn_def_trigger_msg 17 +#define isc_dyn_def_file 36 +#define isc_dyn_mod_database 39 +#define isc_dyn_mod_rel 11 +#define isc_dyn_mod_global_fld 13 +#define isc_dyn_mod_idx 102 +#define isc_dyn_mod_local_fld 14 +#define isc_dyn_mod_sql_fld 216 +#define isc_dyn_mod_view 16 +#define isc_dyn_mod_security_class 122 +#define isc_dyn_mod_trigger 113 +#define isc_dyn_mod_trigger_msg 28 +#define isc_dyn_delete_database 18 +#define isc_dyn_delete_rel 19 +#define isc_dyn_delete_global_fld 20 +#define isc_dyn_delete_local_fld 21 +#define isc_dyn_delete_idx 22 +#define isc_dyn_delete_security_class 123 +#define isc_dyn_delete_dimensions 143 +#define isc_dyn_delete_trigger 23 +#define isc_dyn_delete_trigger_msg 29 +#define isc_dyn_delete_filter 32 +#define isc_dyn_delete_function 33 +#define isc_dyn_delete_shadow 35 +#define isc_dyn_grant 30 +#define isc_dyn_revoke 31 +#define isc_dyn_def_primary_key 37 +#define isc_dyn_def_foreign_key 38 +#define isc_dyn_def_unique 40 +#define isc_dyn_def_procedure 164 +#define isc_dyn_delete_procedure 165 +#define isc_dyn_def_parameter 135 +#define isc_dyn_delete_parameter 136 +#define isc_dyn_mod_procedure 175 +#define isc_dyn_def_log_file 176 +#define isc_dyn_def_cache_file 180 +#define isc_dyn_def_exception 181 +#define isc_dyn_mod_exception 182 +#define isc_dyn_del_exception 183 +#define isc_dyn_drop_log 194 +#define isc_dyn_drop_cache 195 +#define isc_dyn_def_default_log 202 + +/***********************/ +/* View specific stuff */ +/***********************/ + +#define isc_dyn_view_blr 43 +#define isc_dyn_view_source 44 +#define isc_dyn_view_relation 45 +#define isc_dyn_view_context 46 +#define isc_dyn_view_context_name 47 + +/**********************/ +/* Generic attributes */ +/**********************/ + +#define isc_dyn_rel_name 50 +#define isc_dyn_fld_name 51 +#define isc_dyn_new_fld_name 215 +#define isc_dyn_idx_name 52 +#define isc_dyn_description 53 +#define isc_dyn_security_class 54 +#define isc_dyn_system_flag 55 +#define isc_dyn_update_flag 56 +#define isc_dyn_prc_name 166 +#define isc_dyn_prm_name 137 +#define isc_dyn_sql_object 196 +#define isc_dyn_fld_character_set_name 174 + +/********************************/ +/* Relation specific attributes */ +/********************************/ + +#define isc_dyn_rel_dbkey_length 61 +#define isc_dyn_rel_store_trig 62 +#define isc_dyn_rel_modify_trig 63 +#define isc_dyn_rel_erase_trig 64 +#define isc_dyn_rel_store_trig_source 65 +#define isc_dyn_rel_modify_trig_source 66 +#define isc_dyn_rel_erase_trig_source 67 +#define isc_dyn_rel_ext_file 68 +#define isc_dyn_rel_sql_protection 69 +#define isc_dyn_rel_constraint 162 +#define isc_dyn_delete_rel_constraint 163 + +/************************************/ +/* Global field specific attributes */ +/************************************/ + +#define isc_dyn_fld_type 70 +#define isc_dyn_fld_length 71 +#define isc_dyn_fld_scale 72 +#define isc_dyn_fld_sub_type 73 +#define isc_dyn_fld_segment_length 74 +#define isc_dyn_fld_query_header 75 +#define isc_dyn_fld_edit_string 76 +#define isc_dyn_fld_validation_blr 77 +#define isc_dyn_fld_validation_source 78 +#define isc_dyn_fld_computed_blr 79 +#define isc_dyn_fld_computed_source 80 +#define isc_dyn_fld_missing_value 81 +#define isc_dyn_fld_default_value 82 +#define isc_dyn_fld_query_name 83 +#define isc_dyn_fld_dimensions 84 +#define isc_dyn_fld_not_null 85 +#define isc_dyn_fld_precision 86 +#define isc_dyn_fld_char_length 172 +#define isc_dyn_fld_collation 173 +#define isc_dyn_fld_default_source 193 +#define isc_dyn_del_default 197 +#define isc_dyn_del_validation 198 +#define isc_dyn_single_validation 199 +#define isc_dyn_fld_character_set 203 + +/***********************************/ +/* Local field specific attributes */ +/***********************************/ + +#define isc_dyn_fld_source 90 +#define isc_dyn_fld_base_fld 91 +#define isc_dyn_fld_position 92 +#define isc_dyn_fld_update_flag 93 + +/*****************************/ +/* Index specific attributes */ +/*****************************/ + +#define isc_dyn_idx_unique 100 +#define isc_dyn_idx_inactive 101 +#define isc_dyn_idx_type 103 +#define isc_dyn_idx_foreign_key 104 +#define isc_dyn_idx_ref_column 105 +#define isc_dyn_idx_statistic 204 + +/*******************************/ +/* Trigger specific attributes */ +/*******************************/ + +#define isc_dyn_trg_type 110 +#define isc_dyn_trg_blr 111 +#define isc_dyn_trg_source 112 +#define isc_dyn_trg_name 114 +#define isc_dyn_trg_sequence 115 +#define isc_dyn_trg_inactive 116 +#define isc_dyn_trg_msg_number 117 +#define isc_dyn_trg_msg 118 + +/**************************************/ +/* Security Class specific attributes */ +/**************************************/ + +#define isc_dyn_scl_acl 121 +#define isc_dyn_grant_user 130 +#define isc_dyn_grant_user_explicit 219 +#define isc_dyn_grant_proc 186 +#define isc_dyn_grant_trig 187 +#define isc_dyn_grant_view 188 +#define isc_dyn_grant_options 132 +#define isc_dyn_grant_user_group 205 +#define isc_dyn_grant_role 218 + + +/**********************************/ +/* Dimension specific information */ +/**********************************/ + +#define isc_dyn_dim_lower 141 +#define isc_dyn_dim_upper 142 + +/****************************/ +/* File specific attributes */ +/****************************/ + +#define isc_dyn_file_name 125 +#define isc_dyn_file_start 126 +#define isc_dyn_file_length 127 +#define isc_dyn_shadow_number 128 +#define isc_dyn_shadow_man_auto 129 +#define isc_dyn_shadow_conditional 130 + +/********************************/ +/* Log file specific attributes */ +/********************************/ + +#define isc_dyn_log_file_sequence 177 +#define isc_dyn_log_file_partitions 178 +#define isc_dyn_log_file_serial 179 +#define isc_dyn_log_file_overflow 200 +#define isc_dyn_log_file_raw 201 + +/***************************/ +/* Log specific attributes */ +/***************************/ + +#define isc_dyn_log_group_commit_wait 189 +#define isc_dyn_log_buffer_size 190 +#define isc_dyn_log_check_point_length 191 +#define isc_dyn_log_num_of_buffers 192 + +/********************************/ +/* Function specific attributes */ +/********************************/ + +#define isc_dyn_function_name 145 +#define isc_dyn_function_type 146 +#define isc_dyn_func_module_name 147 +#define isc_dyn_func_entry_point 148 +#define isc_dyn_func_return_argument 149 +#define isc_dyn_func_arg_position 150 +#define isc_dyn_func_mechanism 151 +#define isc_dyn_filter_in_subtype 152 +#define isc_dyn_filter_out_subtype 153 + + +#define isc_dyn_description2 154 +#define isc_dyn_fld_computed_source2 155 +#define isc_dyn_fld_edit_string2 156 +#define isc_dyn_fld_query_header2 157 +#define isc_dyn_fld_validation_source2 158 +#define isc_dyn_trg_msg2 159 +#define isc_dyn_trg_source2 160 +#define isc_dyn_view_source2 161 +#define isc_dyn_xcp_msg2 184 + +/*********************************/ +/* Generator specific attributes */ +/*********************************/ + +#define isc_dyn_generator_name 95 +#define isc_dyn_generator_id 96 + +/*********************************/ +/* Procedure specific attributes */ +/*********************************/ + +#define isc_dyn_prc_inputs 167 +#define isc_dyn_prc_outputs 168 +#define isc_dyn_prc_source 169 +#define isc_dyn_prc_blr 170 +#define isc_dyn_prc_source2 171 + +/*********************************/ +/* Parameter specific attributes */ +/*********************************/ + +#define isc_dyn_prm_number 138 +#define isc_dyn_prm_type 139 + +/********************************/ +/* Relation specific attributes */ +/********************************/ + +#define isc_dyn_xcp_msg 185 + +/**********************************************/ +/* Cascading referential integrity values */ +/**********************************************/ +#define isc_dyn_foreign_key_update 205 +#define isc_dyn_foreign_key_delete 206 +#define isc_dyn_foreign_key_cascade 207 +#define isc_dyn_foreign_key_default 208 +#define isc_dyn_foreign_key_null 209 +#define isc_dyn_foreign_key_none 210 + +/***********************/ +/* SQL role values */ +/***********************/ +#define isc_dyn_def_sql_role 211 +#define isc_dyn_sql_role_name 212 +#define isc_dyn_grant_admin_options 213 +#define isc_dyn_del_sql_role 214 +/* 215 & 216 are used some lines above. */ + +/**********************************************/ +/* Generators again */ +/**********************************************/ + +#ifndef __cplusplus /* c definitions */ +#define gds_dyn_delete_generator 217 +#else /* c++ definitions */ +const unsigned char gds_dyn_delete_generator = 217; +#endif + +/****************************/ +/* Last $dyn value assigned */ +/****************************/ + +#define isc_dyn_last_dyn_value 219 + +/******************************************/ +/* Array slice description language (SDL) */ +/******************************************/ + +#define isc_sdl_version1 1 +#define isc_sdl_eoc 255 +#define isc_sdl_relation 2 +#define isc_sdl_rid 3 +#define isc_sdl_field 4 +#define isc_sdl_fid 5 +#define isc_sdl_struct 6 +#define isc_sdl_variable 7 +#define isc_sdl_scalar 8 +#define isc_sdl_tiny_integer 9 +#define isc_sdl_short_integer 10 +#define isc_sdl_long_integer 11 +#define isc_sdl_literal 12 +#define isc_sdl_add 13 +#define isc_sdl_subtract 14 +#define isc_sdl_multiply 15 +#define isc_sdl_divide 16 +#define isc_sdl_negate 17 +#define isc_sdl_eql 18 +#define isc_sdl_neq 19 +#define isc_sdl_gtr 20 +#define isc_sdl_geq 21 +#define isc_sdl_lss 22 +#define isc_sdl_leq 23 +#define isc_sdl_and 24 +#define isc_sdl_or 25 +#define isc_sdl_not 26 +#define isc_sdl_while 27 +#define isc_sdl_assignment 28 +#define isc_sdl_label 29 +#define isc_sdl_leave 30 +#define isc_sdl_begin 31 +#define isc_sdl_end 32 +#define isc_sdl_do3 33 +#define isc_sdl_do2 34 +#define isc_sdl_do1 35 +#define isc_sdl_element 36 + +/********************************************/ +/* International text interpretation values */ +/********************************************/ + +#define isc_interp_eng_ascii 0 +#define isc_interp_jpn_sjis 5 +#define isc_interp_jpn_euc 6 + +/*******************/ +/* SQL definitions */ +/*******************/ + +#define SQL_TEXT 452 +#define SQL_VARYING 448 +#define SQL_SHORT 500 +#define SQL_LONG 496 +#define SQL_FLOAT 482 +#define SQL_DOUBLE 480 +#define SQL_D_FLOAT 530 +#define SQL_TIMESTAMP 510 +#define SQL_BLOB 520 +#define SQL_ARRAY 540 +#define SQL_QUAD 550 +#define SQL_TYPE_TIME 560 +#define SQL_TYPE_DATE 570 +#define SQL_INT64 580 + +/* Historical alias for pre V6 applications */ +#define SQL_DATE SQL_TIMESTAMP + +/*****************/ +/* Blob Subtypes */ +/*****************/ + +/* types less than zero are reserved for customer use */ + +#define isc_blob_untyped 0 + +/* internal subtypes */ + +#define isc_blob_text 1 +#define isc_blob_blr 2 +#define isc_blob_acl 3 +#define isc_blob_ranges 4 +#define isc_blob_summary 5 +#define isc_blob_format 6 +#define isc_blob_tra 7 +#define isc_blob_extfile 8 + +/* the range 20-30 is reserved for dBASE and Paradox types */ + +#define isc_blob_formatted_memo 20 +#define isc_blob_paradox_ole 21 +#define isc_blob_graphic 22 +#define isc_blob_dbase_ole 23 +#define isc_blob_typed_binary 24 + +/* Deprecated definitions maintained for compatibility only */ + +#define isc_info_db_SQL_dialect 62 +#define isc_dpb_SQL_dialect 63 +#define isc_dpb_set_db_SQL_dialect 65 + + +#include "iberror.h" + +#endif /* JRD_IBASE_H */ + diff --git a/libs/ibpp/iberror.h b/libs/ibpp/iberror.h new file mode 100644 index 00000000..653beb6b --- /dev/null +++ b/libs/ibpp/iberror.h @@ -0,0 +1,771 @@ + +#ifndef _JRD_GEN_IBERROR_H +#define _JRD_GEN_IBERROR_H +/* + * The contents of this file are subject to the Interbase Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy + * of the License at http://www.Inprise.com/IPL.html + * + * Software distributed under the License is distributed on an + * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express + * or implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The content of this file was generated by the Firebird project + * using the program jrd/codes.epp + */ +/* + * + * *** WARNING *** - This file is automatically generated by codes.e - do not edit! + * + */ +/* + * MODULE: iberror.h + * DESCRIPTION: ISC error codes + * + */ + + + +/***********************/ +/* ISC Error Codes */ +/***********************/ + +#define isc_facility 20 +#define isc_base 335544320L +#define isc_factor 1 + +#define isc_arg_end 0 /* end of argument list */ +#define isc_arg_gds 1 /* generic DSRI status value */ +#define isc_arg_string 2 /* string argument */ +#define isc_arg_cstring 3 /* count & string argument */ +#define isc_arg_number 4 /* numeric argument (long) */ +#define isc_arg_interpreted 5 /* interpreted status code (string) */ +#define isc_arg_vms 6 /* VAX/VMS status code (long) */ +#define isc_arg_unix 7 /* UNIX error code */ +#define isc_arg_domain 8 /* Apollo/Domain error code */ +#define isc_arg_dos 9 /* MSDOS/OS2 error code */ +#define isc_arg_mpexl 10 /* HP MPE/XL error code */ +#define isc_arg_mpexl_ipc 11 /* HP MPE/XL IPC error code */ +#define isc_arg_next_mach 15 /* NeXT/Mach error code */ +#define isc_arg_netware 16 /* NetWare error code */ +#define isc_arg_win32 17 /* Win32 error code */ +#define isc_arg_warning 18 /* warning argument */ + +#define isc_arith_except 335544321L +#define isc_bad_dbkey 335544322L +#define isc_bad_db_format 335544323L +#define isc_bad_db_handle 335544324L +#define isc_bad_dpb_content 335544325L +#define isc_bad_dpb_form 335544326L +#define isc_bad_req_handle 335544327L +#define isc_bad_segstr_handle 335544328L +#define isc_bad_segstr_id 335544329L +#define isc_bad_tpb_content 335544330L +#define isc_bad_tpb_form 335544331L +#define isc_bad_trans_handle 335544332L +#define isc_bug_check 335544333L +#define isc_convert_error 335544334L +#define isc_db_corrupt 335544335L +#define isc_deadlock 335544336L +#define isc_excess_trans 335544337L +#define isc_from_no_match 335544338L +#define isc_infinap 335544339L +#define isc_infona 335544340L +#define isc_infunk 335544341L +#define isc_integ_fail 335544342L +#define isc_invalid_blr 335544343L +#define isc_io_error 335544344L +#define isc_lock_conflict 335544345L +#define isc_metadata_corrupt 335544346L +#define isc_not_valid 335544347L +#define isc_no_cur_rec 335544348L +#define isc_no_dup 335544349L +#define isc_no_finish 335544350L +#define isc_no_meta_update 335544351L +#define isc_no_priv 335544352L +#define isc_no_recon 335544353L +#define isc_no_record 335544354L +#define isc_no_segstr_close 335544355L +#define isc_obsolete_metadata 335544356L +#define isc_open_trans 335544357L +#define isc_port_len 335544358L +#define isc_read_only_field 335544359L +#define isc_read_only_rel 335544360L +#define isc_read_only_trans 335544361L +#define isc_read_only_view 335544362L +#define isc_req_no_trans 335544363L +#define isc_req_sync 335544364L +#define isc_req_wrong_db 335544365L +#define isc_segment 335544366L +#define isc_segstr_eof 335544367L +#define isc_segstr_no_op 335544368L +#define isc_segstr_no_read 335544369L +#define isc_segstr_no_trans 335544370L +#define isc_segstr_no_write 335544371L +#define isc_segstr_wrong_db 335544372L +#define isc_sys_request 335544373L +#define isc_stream_eof 335544374L +#define isc_unavailable 335544375L +#define isc_unres_rel 335544376L +#define isc_uns_ext 335544377L +#define isc_wish_list 335544378L +#define isc_wrong_ods 335544379L +#define isc_wronumarg 335544380L +#define isc_imp_exc 335544381L +#define isc_random 335544382L +#define isc_fatal_conflict 335544383L +#define isc_badblk 335544384L +#define isc_invpoolcl 335544385L +#define isc_nopoolids 335544386L +#define isc_relbadblk 335544387L +#define isc_blktoobig 335544388L +#define isc_bufexh 335544389L +#define isc_syntaxerr 335544390L +#define isc_bufinuse 335544391L +#define isc_bdbincon 335544392L +#define isc_reqinuse 335544393L +#define isc_badodsver 335544394L +#define isc_relnotdef 335544395L +#define isc_fldnotdef 335544396L +#define isc_dirtypage 335544397L +#define isc_waifortra 335544398L +#define isc_doubleloc 335544399L +#define isc_nodnotfnd 335544400L +#define isc_dupnodfnd 335544401L +#define isc_locnotmar 335544402L +#define isc_badpagtyp 335544403L +#define isc_corrupt 335544404L +#define isc_badpage 335544405L +#define isc_badindex 335544406L +#define isc_dbbnotzer 335544407L +#define isc_tranotzer 335544408L +#define isc_trareqmis 335544409L +#define isc_badhndcnt 335544410L +#define isc_wrotpbver 335544411L +#define isc_wroblrver 335544412L +#define isc_wrodpbver 335544413L +#define isc_blobnotsup 335544414L +#define isc_badrelation 335544415L +#define isc_nodetach 335544416L +#define isc_notremote 335544417L +#define isc_trainlim 335544418L +#define isc_notinlim 335544419L +#define isc_traoutsta 335544420L +#define isc_connect_reject 335544421L +#define isc_dbfile 335544422L +#define isc_orphan 335544423L +#define isc_no_lock_mgr 335544424L +#define isc_ctxinuse 335544425L +#define isc_ctxnotdef 335544426L +#define isc_datnotsup 335544427L +#define isc_badmsgnum 335544428L +#define isc_badparnum 335544429L +#define isc_virmemexh 335544430L +#define isc_blocking_signal 335544431L +#define isc_lockmanerr 335544432L +#define isc_journerr 335544433L +#define isc_keytoobig 335544434L +#define isc_nullsegkey 335544435L +#define isc_sqlerr 335544436L +#define isc_wrodynver 335544437L +#define isc_funnotdef 335544438L +#define isc_funmismat 335544439L +#define isc_bad_msg_vec 335544440L +#define isc_bad_detach 335544441L +#define isc_noargacc_read 335544442L +#define isc_noargacc_write 335544443L +#define isc_read_only 335544444L +#define isc_ext_err 335544445L +#define isc_non_updatable 335544446L +#define isc_no_rollback 335544447L +#define isc_bad_sec_info 335544448L +#define isc_invalid_sec_info 335544449L +#define isc_misc_interpreted 335544450L +#define isc_update_conflict 335544451L +#define isc_unlicensed 335544452L +#define isc_obj_in_use 335544453L +#define isc_nofilter 335544454L +#define isc_shadow_accessed 335544455L +#define isc_invalid_sdl 335544456L +#define isc_out_of_bounds 335544457L +#define isc_invalid_dimension 335544458L +#define isc_rec_in_limbo 335544459L +#define isc_shadow_missing 335544460L +#define isc_cant_validate 335544461L +#define isc_cant_start_journal 335544462L +#define isc_gennotdef 335544463L +#define isc_cant_start_logging 335544464L +#define isc_bad_segstr_type 335544465L +#define isc_foreign_key 335544466L +#define isc_high_minor 335544467L +#define isc_tra_state 335544468L +#define isc_trans_invalid 335544469L +#define isc_buf_invalid 335544470L +#define isc_indexnotdefined 335544471L +#define isc_login 335544472L +#define isc_invalid_bookmark 335544473L +#define isc_bad_lock_level 335544474L +#define isc_relation_lock 335544475L +#define isc_record_lock 335544476L +#define isc_max_idx 335544477L +#define isc_jrn_enable 335544478L +#define isc_old_failure 335544479L +#define isc_old_in_progress 335544480L +#define isc_old_no_space 335544481L +#define isc_no_wal_no_jrn 335544482L +#define isc_num_old_files 335544483L +#define isc_wal_file_open 335544484L +#define isc_bad_stmt_handle 335544485L +#define isc_wal_failure 335544486L +#define isc_walw_err 335544487L +#define isc_logh_small 335544488L +#define isc_logh_inv_version 335544489L +#define isc_logh_open_flag 335544490L +#define isc_logh_open_flag2 335544491L +#define isc_logh_diff_dbname 335544492L +#define isc_logf_unexpected_eof 335544493L +#define isc_logr_incomplete 335544494L +#define isc_logr_header_small 335544495L +#define isc_logb_small 335544496L +#define isc_wal_illegal_attach 335544497L +#define isc_wal_invalid_wpb 335544498L +#define isc_wal_err_rollover 335544499L +#define isc_no_wal 335544500L +#define isc_drop_wal 335544501L +#define isc_stream_not_defined 335544502L +#define isc_wal_subsys_error 335544503L +#define isc_wal_subsys_corrupt 335544504L +#define isc_no_archive 335544505L +#define isc_shutinprog 335544506L +#define isc_range_in_use 335544507L +#define isc_range_not_found 335544508L +#define isc_charset_not_found 335544509L +#define isc_lock_timeout 335544510L +#define isc_prcnotdef 335544511L +#define isc_prcmismat 335544512L +#define isc_wal_bugcheck 335544513L +#define isc_wal_cant_expand 335544514L +#define isc_codnotdef 335544515L +#define isc_xcpnotdef 335544516L +#define isc_except 335544517L +#define isc_cache_restart 335544518L +#define isc_bad_lock_handle 335544519L +#define isc_jrn_present 335544520L +#define isc_wal_err_rollover2 335544521L +#define isc_wal_err_logwrite 335544522L +#define isc_wal_err_jrn_comm 335544523L +#define isc_wal_err_expansion 335544524L +#define isc_wal_err_setup 335544525L +#define isc_wal_err_ww_sync 335544526L +#define isc_wal_err_ww_start 335544527L +#define isc_shutdown 335544528L +#define isc_existing_priv_mod 335544529L +#define isc_primary_key_ref 335544530L +#define isc_primary_key_notnull 335544531L +#define isc_ref_cnstrnt_notfound 335544532L +#define isc_foreign_key_notfound 335544533L +#define isc_ref_cnstrnt_update 335544534L +#define isc_check_cnstrnt_update 335544535L +#define isc_check_cnstrnt_del 335544536L +#define isc_integ_index_seg_del 335544537L +#define isc_integ_index_seg_mod 335544538L +#define isc_integ_index_del 335544539L +#define isc_integ_index_mod 335544540L +#define isc_check_trig_del 335544541L +#define isc_check_trig_update 335544542L +#define isc_cnstrnt_fld_del 335544543L +#define isc_cnstrnt_fld_rename 335544544L +#define isc_rel_cnstrnt_update 335544545L +#define isc_constaint_on_view 335544546L +#define isc_invld_cnstrnt_type 335544547L +#define isc_primary_key_exists 335544548L +#define isc_systrig_update 335544549L +#define isc_not_rel_owner 335544550L +#define isc_grant_obj_notfound 335544551L +#define isc_grant_fld_notfound 335544552L +#define isc_grant_nopriv 335544553L +#define isc_nonsql_security_rel 335544554L +#define isc_nonsql_security_fld 335544555L +#define isc_wal_cache_err 335544556L +#define isc_shutfail 335544557L +#define isc_check_constraint 335544558L +#define isc_bad_svc_handle 335544559L +#define isc_shutwarn 335544560L +#define isc_wrospbver 335544561L +#define isc_bad_spb_form 335544562L +#define isc_svcnotdef 335544563L +#define isc_no_jrn 335544564L +#define isc_transliteration_failed 335544565L +#define isc_start_cm_for_wal 335544566L +#define isc_wal_ovflow_log_required 335544567L +#define isc_text_subtype 335544568L +#define isc_dsql_error 335544569L +#define isc_dsql_command_err 335544570L +#define isc_dsql_constant_err 335544571L +#define isc_dsql_cursor_err 335544572L +#define isc_dsql_datatype_err 335544573L +#define isc_dsql_decl_err 335544574L +#define isc_dsql_cursor_update_err 335544575L +#define isc_dsql_cursor_open_err 335544576L +#define isc_dsql_cursor_close_err 335544577L +#define isc_dsql_field_err 335544578L +#define isc_dsql_internal_err 335544579L +#define isc_dsql_relation_err 335544580L +#define isc_dsql_procedure_err 335544581L +#define isc_dsql_request_err 335544582L +#define isc_dsql_sqlda_err 335544583L +#define isc_dsql_var_count_err 335544584L +#define isc_dsql_stmt_handle 335544585L +#define isc_dsql_function_err 335544586L +#define isc_dsql_blob_err 335544587L +#define isc_collation_not_found 335544588L +#define isc_collation_not_for_charset 335544589L +#define isc_dsql_dup_option 335544590L +#define isc_dsql_tran_err 335544591L +#define isc_dsql_invalid_array 335544592L +#define isc_dsql_max_arr_dim_exceeded 335544593L +#define isc_dsql_arr_range_error 335544594L +#define isc_dsql_trigger_err 335544595L +#define isc_dsql_subselect_err 335544596L +#define isc_dsql_crdb_prepare_err 335544597L +#define isc_specify_field_err 335544598L +#define isc_num_field_err 335544599L +#define isc_col_name_err 335544600L +#define isc_where_err 335544601L +#define isc_table_view_err 335544602L +#define isc_distinct_err 335544603L +#define isc_key_field_count_err 335544604L +#define isc_subquery_err 335544605L +#define isc_expression_eval_err 335544606L +#define isc_node_err 335544607L +#define isc_command_end_err 335544608L +#define isc_index_name 335544609L +#define isc_exception_name 335544610L +#define isc_field_name 335544611L +#define isc_token_err 335544612L +#define isc_union_err 335544613L +#define isc_dsql_construct_err 335544614L +#define isc_field_aggregate_err 335544615L +#define isc_field_ref_err 335544616L +#define isc_order_by_err 335544617L +#define isc_return_mode_err 335544618L +#define isc_extern_func_err 335544619L +#define isc_alias_conflict_err 335544620L +#define isc_procedure_conflict_error 335544621L +#define isc_relation_conflict_err 335544622L +#define isc_dsql_domain_err 335544623L +#define isc_idx_seg_err 335544624L +#define isc_node_name_err 335544625L +#define isc_table_name 335544626L +#define isc_proc_name 335544627L +#define isc_idx_create_err 335544628L +#define isc_wal_shadow_err 335544629L +#define isc_dependency 335544630L +#define isc_idx_key_err 335544631L +#define isc_dsql_file_length_err 335544632L +#define isc_dsql_shadow_number_err 335544633L +#define isc_dsql_token_unk_err 335544634L +#define isc_dsql_no_relation_alias 335544635L +#define isc_indexname 335544636L +#define isc_no_stream_plan 335544637L +#define isc_stream_twice 335544638L +#define isc_stream_not_found 335544639L +#define isc_collation_requires_text 335544640L +#define isc_dsql_domain_not_found 335544641L +#define isc_index_unused 335544642L +#define isc_dsql_self_join 335544643L +#define isc_stream_bof 335544644L +#define isc_stream_crack 335544645L +#define isc_db_or_file_exists 335544646L +#define isc_invalid_operator 335544647L +#define isc_conn_lost 335544648L +#define isc_bad_checksum 335544649L +#define isc_page_type_err 335544650L +#define isc_ext_readonly_err 335544651L +#define isc_sing_select_err 335544652L +#define isc_psw_attach 335544653L +#define isc_psw_start_trans 335544654L +#define isc_invalid_direction 335544655L +#define isc_dsql_var_conflict 335544656L +#define isc_dsql_no_blob_array 335544657L +#define isc_dsql_base_table 335544658L +#define isc_duplicate_base_table 335544659L +#define isc_view_alias 335544660L +#define isc_index_root_page_full 335544661L +#define isc_dsql_blob_type_unknown 335544662L +#define isc_req_max_clones_exceeded 335544663L +#define isc_dsql_duplicate_spec 335544664L +#define isc_unique_key_violation 335544665L +#define isc_srvr_version_too_old 335544666L +#define isc_drdb_completed_with_errs 335544667L +#define isc_dsql_procedure_use_err 335544668L +#define isc_dsql_count_mismatch 335544669L +#define isc_blob_idx_err 335544670L +#define isc_array_idx_err 335544671L +#define isc_key_field_err 335544672L +#define isc_no_delete 335544673L +#define isc_del_last_field 335544674L +#define isc_sort_err 335544675L +#define isc_sort_mem_err 335544676L +#define isc_version_err 335544677L +#define isc_inval_key_posn 335544678L +#define isc_no_segments_err 335544679L +#define isc_crrp_data_err 335544680L +#define isc_rec_size_err 335544681L +#define isc_dsql_field_ref 335544682L +#define isc_req_depth_exceeded 335544683L +#define isc_no_field_access 335544684L +#define isc_no_dbkey 335544685L +#define isc_jrn_format_err 335544686L +#define isc_jrn_file_full 335544687L +#define isc_dsql_open_cursor_request 335544688L +#define isc_ib_error 335544689L +#define isc_cache_redef 335544690L +#define isc_cache_too_small 335544691L +#define isc_log_redef 335544692L +#define isc_log_too_small 335544693L +#define isc_partition_too_small 335544694L +#define isc_partition_not_supp 335544695L +#define isc_log_length_spec 335544696L +#define isc_precision_err 335544697L +#define isc_scale_nogt 335544698L +#define isc_expec_short 335544699L +#define isc_expec_long 335544700L +#define isc_expec_ushort 335544701L +#define isc_like_escape_invalid 335544702L +#define isc_svcnoexe 335544703L +#define isc_net_lookup_err 335544704L +#define isc_service_unknown 335544705L +#define isc_host_unknown 335544706L +#define isc_grant_nopriv_on_base 335544707L +#define isc_dyn_fld_ambiguous 335544708L +#define isc_dsql_agg_ref_err 335544709L +#define isc_complex_view 335544710L +#define isc_unprepared_stmt 335544711L +#define isc_expec_positive 335544712L +#define isc_dsql_sqlda_value_err 335544713L +#define isc_invalid_array_id 335544714L +#define isc_extfile_uns_op 335544715L +#define isc_svc_in_use 335544716L +#define isc_err_stack_limit 335544717L +#define isc_invalid_key 335544718L +#define isc_net_init_error 335544719L +#define isc_loadlib_failure 335544720L +#define isc_network_error 335544721L +#define isc_net_connect_err 335544722L +#define isc_net_connect_listen_err 335544723L +#define isc_net_event_connect_err 335544724L +#define isc_net_event_listen_err 335544725L +#define isc_net_read_err 335544726L +#define isc_net_write_err 335544727L +#define isc_integ_index_deactivate 335544728L +#define isc_integ_deactivate_primary 335544729L +#define isc_cse_not_supported 335544730L +#define isc_tra_must_sweep 335544731L +#define isc_unsupported_network_drive 335544732L +#define isc_io_create_err 335544733L +#define isc_io_open_err 335544734L +#define isc_io_close_err 335544735L +#define isc_io_read_err 335544736L +#define isc_io_write_err 335544737L +#define isc_io_delete_err 335544738L +#define isc_io_access_err 335544739L +#define isc_udf_exception 335544740L +#define isc_lost_db_connection 335544741L +#define isc_no_write_user_priv 335544742L +#define isc_token_too_long 335544743L +#define isc_max_att_exceeded 335544744L +#define isc_login_same_as_role_name 335544745L +#define isc_reftable_requires_pk 335544746L +#define isc_usrname_too_long 335544747L +#define isc_password_too_long 335544748L +#define isc_usrname_required 335544749L +#define isc_password_required 335544750L +#define isc_bad_protocol 335544751L +#define isc_dup_usrname_found 335544752L +#define isc_usrname_not_found 335544753L +#define isc_error_adding_sec_record 335544754L +#define isc_error_modifying_sec_record 335544755L +#define isc_error_deleting_sec_record 335544756L +#define isc_error_updating_sec_db 335544757L +#define isc_sort_rec_size_err 335544758L +#define isc_bad_default_value 335544759L +#define isc_invalid_clause 335544760L +#define isc_too_many_handles 335544761L +#define isc_optimizer_blk_exc 335544762L +#define isc_invalid_string_constant 335544763L +#define isc_transitional_date 335544764L +#define isc_read_only_database 335544765L +#define isc_must_be_dialect_2_and_up 335544766L +#define isc_blob_filter_exception 335544767L +#define isc_exception_access_violation 335544768L +#define isc_exception_datatype_missalignment 335544769L +#define isc_exception_array_bounds_exceeded 335544770L +#define isc_exception_float_denormal_operand 335544771L +#define isc_exception_float_divide_by_zero 335544772L +#define isc_exception_float_inexact_result 335544773L +#define isc_exception_float_invalid_operand 335544774L +#define isc_exception_float_overflow 335544775L +#define isc_exception_float_stack_check 335544776L +#define isc_exception_float_underflow 335544777L +#define isc_exception_integer_divide_by_zero 335544778L +#define isc_exception_integer_overflow 335544779L +#define isc_exception_unknown 335544780L +#define isc_exception_stack_overflow 335544781L +#define isc_exception_sigsegv 335544782L +#define isc_exception_sigill 335544783L +#define isc_exception_sigbus 335544784L +#define isc_exception_sigfpe 335544785L +#define isc_ext_file_delete 335544786L +#define isc_ext_file_modify 335544787L +#define isc_adm_task_denied 335544788L +#define isc_extract_input_mismatch 335544789L +#define isc_insufficient_svc_privileges 335544790L +#define isc_file_in_use 335544791L +#define isc_service_att_err 335544792L +#define isc_ddl_not_allowed_by_db_sql_dial 335544793L +#define isc_cancelled 335544794L +#define isc_unexp_spb_form 335544795L +#define isc_sql_dialect_datatype_unsupport 335544796L +#define isc_svcnouser 335544797L +#define isc_depend_on_uncommitted_rel 335544798L +#define isc_svc_name_missing 335544799L +#define isc_too_many_contexts 335544800L +#define isc_datype_notsup 335544801L +#define isc_dialect_reset_warning 335544802L +#define isc_dialect_not_changed 335544803L +#define isc_database_create_failed 335544804L +#define isc_inv_dialect_specified 335544805L +#define isc_valid_db_dialects 335544806L +#define isc_sqlwarn 335544807L +#define isc_dtype_renamed 335544808L +#define isc_extern_func_dir_error 335544809L +#define isc_date_range_exceeded 335544810L +#define isc_inv_client_dialect_specified 335544811L +#define isc_valid_client_dialects 335544812L +#define isc_optimizer_between_err 335544813L +#define isc_service_not_supported 335544814L +#define isc_generator_name 335544815L +#define isc_udf_name 335544816L +#define isc_bad_limit_param 335544817L +#define isc_bad_skip_param 335544818L +#define isc_io_32bit_exceeded_err 335544819L +#define isc_invalid_savepoint 335544820L +#define isc_dsql_column_pos_err 335544821L +#define isc_dsql_agg_where_err 335544822L +#define isc_dsql_agg_group_err 335544823L +#define isc_dsql_agg_column_err 335544824L +#define isc_dsql_agg_having_err 335544825L +#define isc_dsql_agg_nested_err 335544826L +#define isc_exec_sql_invalid_arg 335544827L +#define isc_exec_sql_invalid_req 335544828L +#define isc_exec_sql_invalid_var 335544829L +#define isc_exec_sql_max_call_exceeded 335544830L +#define isc_conf_access_denied 335544831L +#define isc_gfix_db_name 335740929L +#define isc_gfix_invalid_sw 335740930L +#define isc_gfix_incmp_sw 335740932L +#define isc_gfix_replay_req 335740933L +#define isc_gfix_pgbuf_req 335740934L +#define isc_gfix_val_req 335740935L +#define isc_gfix_pval_req 335740936L +#define isc_gfix_trn_req 335740937L +#define isc_gfix_full_req 335740940L +#define isc_gfix_usrname_req 335740941L +#define isc_gfix_pass_req 335740942L +#define isc_gfix_subs_name 335740943L +#define isc_gfix_wal_req 335740944L +#define isc_gfix_sec_req 335740945L +#define isc_gfix_nval_req 335740946L +#define isc_gfix_type_shut 335740947L +#define isc_gfix_retry 335740948L +#define isc_gfix_retry_db 335740951L +#define isc_gfix_exceed_max 335740991L +#define isc_gfix_corrupt_pool 335740992L +#define isc_gfix_mem_exhausted 335740993L +#define isc_gfix_bad_pool 335740994L +#define isc_gfix_trn_not_valid 335740995L +#define isc_gfix_unexp_eoi 335741012L +#define isc_gfix_recon_fail 335741018L +#define isc_gfix_trn_unknown 335741036L +#define isc_gfix_mode_req 335741038L +#define isc_gfix_opt_SQL_dialect 335741039L +#define isc_dsql_dbkey_from_non_table 336003074L +#define isc_dsql_transitional_numeric 336003075L +#define isc_dsql_dialect_warning_expr 336003076L +#define isc_sql_db_dialect_dtype_unsupport 336003077L +#define isc_isc_sql_dialect_conflict_num 336003079L +#define isc_dsql_warning_number_ambiguous 336003080L +#define isc_dsql_warning_number_ambiguous1 336003081L +#define isc_dsql_warn_precision_ambiguous 336003082L +#define isc_dsql_warn_precision_ambiguous1 336003083L +#define isc_dsql_warn_precision_ambiguous2 336003084L +#define isc_dsql_ambiguous_field_name 336003085L +#define isc_dsql_udf_return_pos_err 336003086L +#define isc_dsql_invalid_label 336003087L +#define isc_dsql_datatypes_not_comparable 336003088L +#define isc_dyn_role_does_not_exist 336068796L +#define isc_dyn_no_grant_admin_opt 336068797L +#define isc_dyn_user_not_role_member 336068798L +#define isc_dyn_delete_role_failed 336068799L +#define isc_dyn_grant_role_to_user 336068800L +#define isc_dyn_inv_sql_role_name 336068801L +#define isc_dyn_dup_sql_role 336068802L +#define isc_dyn_kywd_spec_for_role 336068803L +#define isc_dyn_roles_not_supported 336068804L +#define isc_dyn_domain_name_exists 336068812L +#define isc_dyn_field_name_exists 336068813L +#define isc_dyn_dependency_exists 336068814L +#define isc_dyn_dtype_invalid 336068815L +#define isc_dyn_char_fld_too_small 336068816L +#define isc_dyn_invalid_dtype_conversion 336068817L +#define isc_dyn_dtype_conv_invalid 336068818L +#define isc_dyn_zero_len_id 336068820L +#define isc_gbak_unknown_switch 336330753L +#define isc_gbak_page_size_missing 336330754L +#define isc_gbak_page_size_toobig 336330755L +#define isc_gbak_redir_ouput_missing 336330756L +#define isc_gbak_switches_conflict 336330757L +#define isc_gbak_unknown_device 336330758L +#define isc_gbak_no_protection 336330759L +#define isc_gbak_page_size_not_allowed 336330760L +#define isc_gbak_multi_source_dest 336330761L +#define isc_gbak_filename_missing 336330762L +#define isc_gbak_dup_inout_names 336330763L +#define isc_gbak_inv_page_size 336330764L +#define isc_gbak_db_specified 336330765L +#define isc_gbak_db_exists 336330766L +#define isc_gbak_unk_device 336330767L +#define isc_gbak_blob_info_failed 336330772L +#define isc_gbak_unk_blob_item 336330773L +#define isc_gbak_get_seg_failed 336330774L +#define isc_gbak_close_blob_failed 336330775L +#define isc_gbak_open_blob_failed 336330776L +#define isc_gbak_put_blr_gen_id_failed 336330777L +#define isc_gbak_unk_type 336330778L +#define isc_gbak_comp_req_failed 336330779L +#define isc_gbak_start_req_failed 336330780L +#define isc_gbak_rec_failed 336330781L +#define isc_gbak_rel_req_failed 336330782L +#define isc_gbak_db_info_failed 336330783L +#define isc_gbak_no_db_desc 336330784L +#define isc_gbak_db_create_failed 336330785L +#define isc_gbak_decomp_len_error 336330786L +#define isc_gbak_tbl_missing 336330787L +#define isc_gbak_blob_col_missing 336330788L +#define isc_gbak_create_blob_failed 336330789L +#define isc_gbak_put_seg_failed 336330790L +#define isc_gbak_rec_len_exp 336330791L +#define isc_gbak_inv_rec_len 336330792L +#define isc_gbak_exp_data_type 336330793L +#define isc_gbak_gen_id_failed 336330794L +#define isc_gbak_unk_rec_type 336330795L +#define isc_gbak_inv_bkup_ver 336330796L +#define isc_gbak_missing_bkup_desc 336330797L +#define isc_gbak_string_trunc 336330798L +#define isc_gbak_cant_rest_record 336330799L +#define isc_gbak_send_failed 336330800L +#define isc_gbak_no_tbl_name 336330801L +#define isc_gbak_unexp_eof 336330802L +#define isc_gbak_db_format_too_old 336330803L +#define isc_gbak_inv_array_dim 336330804L +#define isc_gbak_xdr_len_expected 336330807L +#define isc_gbak_open_bkup_error 336330817L +#define isc_gbak_open_error 336330818L +#define isc_gbak_missing_block_fac 336330934L +#define isc_gbak_inv_block_fac 336330935L +#define isc_gbak_block_fac_specified 336330936L +#define isc_gbak_missing_username 336330940L +#define isc_gbak_missing_password 336330941L +#define isc_gbak_missing_skipped_bytes 336330952L +#define isc_gbak_inv_skipped_bytes 336330953L +#define isc_gbak_err_restore_charset 336330965L +#define isc_gbak_err_restore_collation 336330967L +#define isc_gbak_read_error 336330972L +#define isc_gbak_write_error 336330973L +#define isc_gbak_db_in_use 336330985L +#define isc_gbak_sysmemex 336330990L +#define isc_gbak_restore_role_failed 336331002L +#define isc_gbak_role_op_missing 336331005L +#define isc_gbak_page_buffers_missing 336331010L +#define isc_gbak_page_buffers_wrong_param 336331011L +#define isc_gbak_page_buffers_restore 336331012L +#define isc_gbak_inv_size 336331014L +#define isc_gbak_file_outof_sequence 336331015L +#define isc_gbak_join_file_missing 336331016L +#define isc_gbak_stdin_not_supptd 336331017L +#define isc_gbak_stdout_not_supptd 336331018L +#define isc_gbak_bkup_corrupt 336331019L +#define isc_gbak_unk_db_file_spec 336331020L +#define isc_gbak_hdr_write_failed 336331021L +#define isc_gbak_disk_space_ex 336331022L +#define isc_gbak_size_lt_min 336331023L +#define isc_gbak_svc_name_missing 336331025L +#define isc_gbak_not_ownr 336331026L +#define isc_gbak_mode_req 336331031L +#define isc_gbak_just_data 336331033L +#define isc_gbak_data_only 336331034L +#define isc_gsec_cant_open_db 336723983L +#define isc_gsec_switches_error 336723984L +#define isc_gsec_no_op_spec 336723985L +#define isc_gsec_no_usr_name 336723986L +#define isc_gsec_err_add 336723987L +#define isc_gsec_err_modify 336723988L +#define isc_gsec_err_find_mod 336723989L +#define isc_gsec_err_rec_not_found 336723990L +#define isc_gsec_err_delete 336723991L +#define isc_gsec_err_find_del 336723992L +#define isc_gsec_err_find_disp 336723996L +#define isc_gsec_inv_param 336723997L +#define isc_gsec_op_specified 336723998L +#define isc_gsec_pw_specified 336723999L +#define isc_gsec_uid_specified 336724000L +#define isc_gsec_gid_specified 336724001L +#define isc_gsec_proj_specified 336724002L +#define isc_gsec_org_specified 336724003L +#define isc_gsec_fname_specified 336724004L +#define isc_gsec_mname_specified 336724005L +#define isc_gsec_lname_specified 336724006L +#define isc_gsec_inv_switch 336724008L +#define isc_gsec_amb_switch 336724009L +#define isc_gsec_no_op_specified 336724010L +#define isc_gsec_params_not_allowed 336724011L +#define isc_gsec_incompat_switch 336724012L +#define isc_gsec_inv_username 336724044L +#define isc_gsec_inv_pw_length 336724045L +#define isc_gsec_db_specified 336724046L +#define isc_gsec_db_admin_specified 336724047L +#define isc_gsec_db_admin_pw_specified 336724048L +#define isc_gsec_sql_role_specified 336724049L +#define isc_license_no_file 336789504L +#define isc_license_op_specified 336789523L +#define isc_license_op_missing 336789524L +#define isc_license_inv_switch 336789525L +#define isc_license_inv_switch_combo 336789526L +#define isc_license_inv_op_combo 336789527L +#define isc_license_amb_switch 336789528L +#define isc_license_inv_parameter 336789529L +#define isc_license_param_specified 336789530L +#define isc_license_param_req 336789531L +#define isc_license_syntx_error 336789532L +#define isc_license_dup_id 336789534L +#define isc_license_inv_id_key 336789535L +#define isc_license_err_remove 336789536L +#define isc_license_err_update 336789537L +#define isc_license_err_convert 336789538L +#define isc_license_err_unk 336789539L +#define isc_license_svc_err_add 336789540L +#define isc_license_svc_err_remove 336789541L +#define isc_license_eval_exists 336789563L +#define isc_gstat_unknown_switch 336920577L +#define isc_gstat_retry 336920578L +#define isc_gstat_wrong_ods 336920579L +#define isc_gstat_unexpected_eof 336920580L +#define isc_gstat_open_err 336920605L +#define isc_gstat_read_err 336920606L +#define isc_gstat_sysmemex 336920607L +#define isc_err_max 713 + +#endif /* JRD_GEN_IBERROR_H */ diff --git a/libs/ibpp/include/stg/ibpp.h b/libs/ibpp/include/stg/ibpp.h new file mode 100644 index 00000000..f666b16d --- /dev/null +++ b/libs/ibpp/include/stg/ibpp.h @@ -0,0 +1,929 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: ibpp.h,v 1.3 2007/10/28 11:17:44 nobunaga Exp $ +// Subject : IBPP public header file. This is _the_ only file you include in +// your application files when developing with IBPP. +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +// Contributor(s): +// +// Olivier Mascia, main coding +// Matt Hortman, initial linux port +// Mark Jordan, design contributions +// Maxim Abrashkin, enhancement patches +// Torsten Martinsen, enhancement patches +// Michael Hieke, darwin (OS X) port, enhancement patches +// Val Samko, enhancement patches and debugging +// Mike Nordell, invaluable C++ advices +// Claudio Valderrama, help with not-so-well documented IB/FB features +// Many others, excellent suggestions, bug finding, and support +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// Tabulations should be set every four characters when editing this file. +// +// When compiling a project using IBPP, the following defines should be made +// on the command-line (or in makefiles) according to the OS platform and +// compiler used. +// +// Select the platform: IBPP_WINDOWS | IBPP_LINUX | IBPP_DARWIN +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef __IBPP_H__ +#define __IBPP_H__ + +#if !defined(IBPP_WINDOWS) && !defined(IBPP_LINUX) && !defined(IBPP_DARWIN) +#error Please define IBPP_WINDOWS/IBPP_LINUX/IBPP_DARWIN before compiling ! +#endif + +#if !defined(__BCPLUSPLUS__) && !defined(__GNUC__) && !defined(_MSC_VER) && !defined(__DMC__) +#error Your compiler is not recognized. +#endif + +#if defined(IBPP_LINUX) || defined(IBPP_DARWIN) +#define IBPP_UNIX // IBPP_UNIX stands as a common denominator to *NIX flavours +#endif + +// IBPP is written for 32 bits systems or higher. +// The standard type 'int' is assumed to be at least 32 bits. +// And the standard type 'short' is assumed to be exactly 16 bits. +// Everywhere possible, where the exact size of an integer does not matter, +// the standard type 'int' is used. And where an exact integer size is required +// the standard exact precision types definitions of C 99 standard are used. + +#if defined(_MSC_VER) || defined(__DMC__) || defined(__BCPLUSPLUS__) +// C99 §7.18.1.1 Exact-width integer types (only those used by IBPP) +#if defined(_MSC_VER) && (_MSC_VER < 1300) // MSVC 6 should be < 1300 + typedef short int16_t; + typedef int int32_t; + typedef unsigned int uint32_t; +#else + typedef __int16 int16_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; +#endif + typedef __int64 int64_t; +#else + #include // C99 (§7.18) integer types definitions +#endif + +#if !defined(_) +#define _(s) s +#endif + +#include +#include +#include + +namespace IBPP +{ + // Typically you use this constant in a call IBPP::CheckVersion as in: + // if (! IBPP::CheckVersion(IBPP::Version)) { throw .... ; } + const uint32_t Version = (2<<24) + (5<<16) + (3<<8) + 0; // Version == 2.5.3.0 + + // Dates range checking + const int MinDate = -693594; // 1 JAN 0001 + const int MaxDate = 2958464; // 31 DEC 9999 + + // Transaction Access Modes + enum TAM {amWrite, amRead}; + + // Transaction Isolation Levels + enum TIL {ilConcurrency, ilReadDirty, ilReadCommitted, ilConsistency}; + + // Transaction Lock Resolution + enum TLR {lrWait, lrNoWait}; + + // Transaction Table Reservation + enum TTR {trSharedWrite, trSharedRead, trProtectedWrite, trProtectedRead}; + + // Prepared Statement Types + enum STT {stUnknown, stUnsupported, + stSelect, stInsert, stUpdate, stDelete, stDDL, stExecProcedure, + stSelectUpdate, stSetGenerator, stSavePoint}; + + // SQL Data Types + enum SDT {sdArray, sdBlob, sdDate, sdTime, sdTimestamp, sdString, + sdSmallint, sdInteger, sdLargeint, sdFloat, sdDouble}; + + // Array Data Types + enum ADT {adDate, adTime, adTimestamp, adString, + adBool, adInt16, adInt32, adInt64, adFloat, adDouble}; + + // Database::Shutdown Modes + enum DSM {dsForce, dsDenyTrans, dsDenyAttach}; + + // Service::StartBackup && Service::StartRestore Flags + enum BRF { + brVerbose = 0x1, + // Backup flags + brIgnoreChecksums = 0x100, brIgnoreLimbo = 0x200, + brMetadataOnly = 0x400, brNoGarbageCollect = 0x800, + brNonTransportable = 0x1000, brConvertExtTables = 0x2000, + // Restore flags + brReplace = 0x10000, brDeactivateIdx = 0x20000, + brNoShadow = 0x40000, brNoValidity = 0x80000, + brPerTableCommit = 0x100000, brUseAllSpace = 0x200000 + }; + + // Service::Repair Flags + enum RPF + { + // Mandatory and mutually exclusives + rpMendRecords = 0x1, rpValidatePages = 0x2, rpValidateFull = 0x4, + // Options + rpReadOnly = 0x100, rpIgnoreChecksums = 0x200, rpKillShadows = 0x400 + }; + + // TransactionFactory Flags + enum TFF {tfIgnoreLimbo = 0x1, tfAutoCommit = 0x2, tfNoAutoUndo = 0x4}; + + /* IBPP never return any error codes. It throws exceptions. + * On database engine reported errors, an IBPP::SQLException is thrown. + * In all other cases, IBPP throws IBPP::LogicException. + * Also note that the runtime and the language might also throw exceptions + * while executing some IBPP methods. A failing new operator will throw + * std::bad_alloc, IBPP does nothing to alter the standard behaviour. + * + * std::exception + * | + * IBPP::Exception + * / \ + * IBPP::LogicException IBPP::SQLException + * | + * IBPP::WrongType + */ + + class Exception : public std::exception + { + public: + virtual const char* Origin() const throw() = 0; + virtual const char* ErrorMessage() const throw() = 0; // Deprecated, use what() + virtual const char* what() const throw() = 0; + virtual ~Exception() throw(); + }; + + class LogicException : public Exception + { + public: + virtual ~LogicException() throw(); + }; + + class SQLException : public Exception + { + public: + virtual int SqlCode() const throw() = 0; + virtual int EngineCode() const throw() = 0; + + virtual ~SQLException() throw(); + }; + + class WrongType : public LogicException + { + public: + virtual ~WrongType() throw(); + }; + + /* Classes Date, Time, Timestamp and DBKey are 'helper' classes. They help + * in retrieving or setting some special SQL types. Dates, times and dbkeys + * are often read and written as strings in SQL scripts. When programming + * with IBPP, we handle those data with these specific classes, which + * enhance their usefullness and free us of format problems (M/D/Y, D/M/Y, + * Y-M-D ?, and so on...). */ + + /* Class Date represent purely a Date (no time part specified). It is + * usefull in interactions with the SQL DATE type of Interbase. You can add + * or substract a number from a Date, that will modify it to represent the + * correct date, X days later or sooner. All the Y2K details taken into + * account. + * The full range goes from integer values IBPP::MinDate to IBPP::MaxDate + * which means from 01 Jan 0001 to 31 Dec 9999. ( Which is inherently + * incorrect as this assumes Gregorian calendar. ) */ + + class Timestamp; // Cross-reference between Timestamp, Date and Time + + class Date + { + protected: + int mDate; // The date : 1 == 1 Jan 1900 + + public: + void Clear() { mDate = MinDate - 1; } + void Today(); + void SetDate(int year, int month, int day); + void SetDate(int dt); + void GetDate(int& year, int& month, int& day) const; + int GetDate() const { return mDate; } + int Year() const; + int Month() const; + int Day() const; + void Add(int days); + void StartOfMonth(); + void EndOfMonth(); + + Date() { Clear(); } + Date(int dt) { SetDate(dt); } + Date(int year, int month, int day); + Date(const Date&); // Copy Constructor + Date& operator=(const Timestamp&); // Timestamp Assignment operator + Date& operator=(const Date&); // Date Assignment operator + + bool operator==(const Date& rv) const { return mDate == rv.GetDate(); } + bool operator!=(const Date& rv) const { return mDate != rv.GetDate(); } + bool operator<(const Date& rv) const { return mDate < rv.GetDate(); } + bool operator>(const Date& rv) const { return mDate > rv.GetDate(); } + + virtual ~Date() { } + }; + + /* Class Time represent purely a Time. It is usefull in interactions + * with the SQL TIME type of Interbase. */ + + class Time + { + protected: + int mTime; // The time, in ten-thousandths of seconds since midnight + + public: + void Clear() { mTime = 0; } + void Now(); + void SetTime(int hour, int minute, int second, int tenthousandths = 0); + void SetTime(int tm); + void GetTime(int& hour, int& minute, int& second) const; + void GetTime(int& hour, int& minute, int& second, int& tenthousandths) const; + int GetTime() const { return mTime; } + int Hours() const; + int Minutes() const; + int Seconds() const; + int SubSeconds() const; // Actually tenthousandths of seconds + Time() { Clear(); } + Time(int tm) { SetTime(tm); } + Time(int hour, int minute, int second, int tenthousandths = 0); + Time(const Time&); // Copy Constructor + Time& operator=(const Timestamp&); // Timestamp Assignment operator + Time& operator=(const Time&); // Time Assignment operator + + bool operator==(const Time& rv) const { return mTime == rv.GetTime(); } + bool operator!=(const Time& rv) const { return mTime != rv.GetTime(); } + bool operator<(const Time& rv) const { return mTime < rv.GetTime(); } + bool operator>(const Time& rv) const { return mTime > rv.GetTime(); } + + virtual ~Time() { } + }; + + /* Class Timestamp represent a date AND a time. It is usefull in + * interactions with the SQL TIMESTAMP type of Interbase. This class + * inherits from Date and Time and completely inline implements its small + * specific details. */ + + class Timestamp : public Date, public Time + { + public: + void Clear() { Date::Clear(); Time::Clear(); } + void Today() { Date::Today(); Time::Clear(); } + void Now() { Date::Today(); Time::Now(); } + + Timestamp() { Clear(); } + + Timestamp(int y, int m, int d) + { Date::SetDate(y, m, d); Time::Clear(); } + + Timestamp(int y, int mo, int d, int h, int mi, int s, int t = 0) + { Date::SetDate(y, mo, d); Time::SetTime(h, mi, s, t); } + + Timestamp(const Timestamp& rv) + : Date(rv.mDate), Time(rv.mTime) {} // Copy Constructor + + Timestamp(const Date& rv) + { mDate = rv.GetDate(); mTime = 0; } + + Timestamp(const Time& rv) + { mDate = 0; mTime = rv.GetTime(); } + + Timestamp& operator=(const Timestamp& rv) // Timestamp Assignment operator + { mDate = rv.mDate; mTime = rv.mTime; return *this; } + + Timestamp& operator=(const Date& rv) // Date Assignment operator + { mDate = rv.GetDate(); return *this; } + + Timestamp& operator=(const Time& rv) // Time Assignment operator + { mTime = rv.GetTime(); return *this; } + + bool operator==(const Timestamp& rv) const + { return (mDate == rv.GetDate()) && (mTime == rv.GetTime()); } + + bool operator!=(const Timestamp& rv) const + { return (mDate != rv.GetDate()) || (mTime != rv.GetTime()); } + + bool operator<(const Timestamp& rv) const + { return (mDate < rv.GetDate()) || + (mDate == rv.GetDate() && mTime < rv.GetTime()); } + + bool operator>(const Timestamp& rv) const + { return (mDate > rv.GetDate()) || + (mDate == rv.GetDate() && mTime > rv.GetTime()); } + + ~Timestamp() { } + }; + + /* Class DBKey can store a DBKEY, that special value which the hidden + * RDB$DBKEY can give you from a select statement. A DBKey is nothing + * specific to IBPP. It's a feature of the Firebird database engine. See its + * documentation for more information. */ + + class DBKey + { + private: + std::string mDBKey; // Stores the binary DBKey + mutable std::string mString;// String (temporary) representation of it + + public: + void Clear(); + int Size() const { return (int)mDBKey.size(); } + void SetKey(const void*, int size); + void GetKey(void*, int size) const; + const char* AsString() const; + + DBKey& operator=(const DBKey&); // Assignment operator + DBKey(const DBKey&); // Copy Constructor + DBKey() { } + ~DBKey() { } + }; + + /* Class User wraps all the information about a user that the engine can manage. */ + + class User + { + public: + std::string username; + std::string password; + std::string firstname; + std::string middlename; + std::string lastname; + uint32_t userid; // Only relevant on unixes + uint32_t groupid; // Only relevant on unixes + + private: + void copyfrom(const User& r); + + public: + void clear(); + User& operator=(const User& r) { copyfrom(r); return *this; } + User(const User& r) { copyfrom(r); } + User() : userid(0), groupid(0) { } + ~User() { } + }; + + // Interface Wrapper + template + class Ptr + { + private: + T* mObject; + + public: + void clear() + { + if (mObject != 0) { mObject->Release(); mObject = 0; } + } + + T* intf() const { return mObject; } + T* operator->() const { return mObject; } + + bool operator==(const T* p) const { return mObject == p; } + bool operator==(const Ptr& r) const { return mObject == r.mObject; } + bool operator!=(const T* p) const { return mObject != p; } + bool operator!=(const Ptr& r) const { return mObject != r.mObject; } + + Ptr& operator=(T* p) + { + // AddRef _before_ Release gives correct behaviour on self-assigns + T* tmp = (p == 0 ? 0 : p->AddRef()); // Take care of 0 + if (mObject != 0) mObject->Release(); + mObject = tmp; return *this; + } + + Ptr& operator=(const Ptr& r) + { + // AddRef _before_ Release gives correct behaviour on self-assigns + T* tmp = (r.intf() == 0 ? 0 : r->AddRef());// Take care of 0 + if (mObject != 0) mObject->Release(); + mObject = tmp; return *this; + } + + Ptr(T* p) : mObject(p == 0 ? 0 : p->AddRef()) { } + Ptr(const Ptr& r) : mObject(r.intf() == 0 ? 0 : r->AddRef()) { } + + Ptr() : mObject(0) { } + ~Ptr() { clear(); } + }; + + // --- Interface Classes --- // + + /* Interfaces IBlob, IArray, IService, IDatabase, ITransaction and + * IStatement are at the core of IBPP. Though it is possible to program your + * applications by using theses interfaces directly (as was the case with + * IBPP 1.x), you should refrain from using them and prefer the new IBPP + * Objects Blob, Array, ... (without the I in front). Those new objects are + * typedef'd right after each interface class definition as you can read + * below. If you program using the Blob (instead of the IBlob interface + * itself), you'll never have to care about AddRef/Release and you'll never + * have to care about deleting your objects. */ + + class IBlob; typedef Ptr Blob; + class IArray; typedef Ptr Array; + class IService; typedef Ptr Service; + class IDatabase; typedef Ptr Database; + class ITransaction; typedef Ptr Transaction; + class IStatement; typedef Ptr Statement; + class IEvents; typedef Ptr Events; + class IRow; typedef Ptr Row; + + /* IBlob is the interface to the blob capabilities of IBPP. Blob is the + * object class you actually use in your programming. In Firebird, at the + * row level, a blob is merely a handle to a blob, stored elsewhere in the + * database. Blob allows you to retrieve such a handle and then read from or + * write to the blob, much in the same manner than you would do with a file. */ + + class IBlob + { + public: + virtual void Create() = 0; + virtual void Open() = 0; + virtual void Close() = 0; + virtual void Cancel() = 0; + virtual int Read(void*, int size) = 0; + virtual void Write(const void*, int size) = 0; + virtual void Info(int* Size, int* Largest, int* Segments) = 0; + + virtual void Save(const std::string& data) = 0; + virtual void Load(std::string& data) = 0; + + virtual Database DatabasePtr() const = 0; + virtual Transaction TransactionPtr() const = 0; + + virtual IBlob* AddRef() = 0; + virtual void Release() = 0; + + virtual ~IBlob() { } + }; + + /* IArray is the interface to the array capabilities of IBPP. Array is the + * object class you actually use in your programming. With an Array object, you + * can create, read and write Interbase Arrays, as a whole or in slices. */ + + class IArray + { + public: + virtual void Describe(const std::string& table, const std::string& column) = 0; + virtual void ReadTo(ADT, void* buffer, int elemcount) = 0; + virtual void WriteFrom(ADT, const void* buffer, int elemcount) = 0; + virtual SDT ElementType() = 0; + virtual int ElementSize() = 0; + virtual int ElementScale() = 0; + virtual int Dimensions() = 0; + virtual void Bounds(int dim, int* low, int* high) = 0; + virtual void SetBounds(int dim, int low, int high) = 0; + + virtual Database DatabasePtr() const = 0; + virtual Transaction TransactionPtr() const = 0; + + virtual IArray* AddRef() = 0; + virtual void Release() = 0; + + virtual ~IArray() { } + }; + + /* IService is the interface to the service capabilities of IBPP. Service is + * the object class you actually use in your programming. With a Service + * object, you can do some maintenance work of databases and servers + * (backup, restore, create/update users, ...) */ + + class IService + { + public: + virtual void Connect() = 0; + virtual bool Connected() = 0; + virtual void Disconnect() = 0; + + virtual void GetVersion(std::string& version) = 0; + + virtual void AddUser(const User&) = 0; + virtual void GetUser(User&) = 0; + virtual void GetUsers(std::vector&) = 0; + virtual void ModifyUser(const User&) = 0; + virtual void RemoveUser(const std::string& username) = 0; + + virtual void SetPageBuffers(const std::string& dbfile, int buffers) = 0; + virtual void SetSweepInterval(const std::string& dbfile, int sweep) = 0; + virtual void SetSyncWrite(const std::string& dbfile, bool) = 0; + virtual void SetReadOnly(const std::string& dbfile, bool) = 0; + virtual void SetReserveSpace(const std::string& dbfile, bool) = 0; + + virtual void Shutdown(const std::string& dbfile, DSM mode, int sectimeout) = 0; + virtual void Restart(const std::string& dbfile) = 0; + virtual void Sweep(const std::string& dbfile) = 0; + virtual void Repair(const std::string& dbfile, RPF flags) = 0; + + virtual void StartBackup(const std::string& dbfile, + const std::string& bkfile, BRF flags = BRF(0)) = 0; + virtual void StartRestore(const std::string& bkfile, const std::string& dbfile, + int pagesize = 0, BRF flags = BRF(0)) = 0; + + virtual const char* WaitMsg() = 0; // With reporting (does not block) + virtual void Wait() = 0; // Without reporting (does block) + + virtual IService* AddRef() = 0; + virtual void Release() = 0; + + virtual ~IService() { } + }; + + /* IDatabase is the interface to the database connections in IBPP. Database + * is the object class you actually use in your programming. With a Database + * object, you can create/drop/connect databases. */ + + class EventInterface; // Cross-reference between EventInterface and IDatabase + + class IDatabase + { + public: + virtual const char* ServerName() const = 0; + virtual const char* DatabaseName() const = 0; + virtual const char* Username() const = 0; + virtual const char* UserPassword() const = 0; + virtual const char* RoleName() const = 0; + virtual const char* CharSet() const = 0; + virtual const char* CreateParams() const = 0; + + virtual void Info(int* ODS, int* ODSMinor, int* PageSize, + int* Pages, int* Buffers, int* Sweep, bool* Sync, + bool* Reserve) = 0; + virtual void Statistics(int* Fetches, int* Marks, + int* Reads, int* Writes) = 0; + virtual void Counts(int* Insert, int* Update, int* Delete, + int* ReadIdx, int* ReadSeq) = 0; + virtual void Users(std::vector& users) = 0; + virtual int Dialect() = 0; + + virtual void Create(int dialect) = 0; + virtual void Connect() = 0; + virtual bool Connected() = 0; + virtual void Inactivate() = 0; + virtual void Disconnect() = 0; + virtual void Drop() = 0; + + virtual IDatabase* AddRef() = 0; + virtual void Release() = 0; + + virtual ~IDatabase() { } + }; + + /* ITransaction is the interface to the transaction connections in IBPP. + * Transaction is the object class you actually use in your programming. A + * Transaction object can be associated with more than one Database, + * allowing for distributed transactions spanning multiple databases, + * possibly located on different servers. IBPP is one among the few + * programming interfaces to Firebird that allows you to support distributed + * transactions. */ + + class ITransaction + { + public: + virtual void AttachDatabase(Database db, TAM am = amWrite, + TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0)) = 0; + virtual void DetachDatabase(Database db) = 0; + virtual void AddReservation(Database db, + const std::string& table, TTR tr) = 0; + + virtual void Start() = 0; + virtual bool Started() = 0; + virtual void Commit() = 0; + virtual void Rollback() = 0; + virtual void CommitRetain() = 0; + virtual void RollbackRetain() = 0; + + virtual ITransaction* AddRef() = 0; + virtual void Release() = 0; + + virtual ~ITransaction() { } + }; + + /* + * Class Row can hold all the values of a row (from a SELECT for instance). + */ + + class IRow + { + public: + virtual void SetNull(int) = 0; + virtual void Set(int, bool) = 0; + virtual void Set(int, const void*, int) = 0; // byte buffers + virtual void Set(int, const char*) = 0; // c-string + virtual void Set(int, const std::string&) = 0; + virtual void Set(int, int16_t) = 0; + virtual void Set(int, int32_t) = 0; + virtual void Set(int, int64_t) = 0; + virtual void Set(int, float) = 0; + virtual void Set(int, double) = 0; + virtual void Set(int, const Timestamp&) = 0; + virtual void Set(int, const Date&) = 0; + virtual void Set(int, const Time&) = 0; + virtual void Set(int, const DBKey&) = 0; + virtual void Set(int, const Blob&) = 0; + virtual void Set(int, const Array&) = 0; + + virtual bool IsNull(int) = 0; + virtual bool Get(int, bool&) = 0; + virtual bool Get(int, void*, int&) = 0; // byte buffers + virtual bool Get(int, std::string&) = 0; + virtual bool Get(int, int16_t&) = 0; + virtual bool Get(int, int32_t&) = 0; + virtual bool Get(int, int64_t&) = 0; + virtual bool Get(int, float&) = 0; + virtual bool Get(int, double&) = 0; + virtual bool Get(int, Timestamp&) = 0; + virtual bool Get(int, Date&) = 0; + virtual bool Get(int, Time&) = 0; + virtual bool Get(int, DBKey&) = 0; + virtual bool Get(int, Blob&) = 0; + virtual bool Get(int, Array&) = 0; + + virtual bool IsNull(const std::string&) = 0; + virtual bool Get(const std::string&, bool&) = 0; + virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers + virtual bool Get(const std::string&, std::string&) = 0; + virtual bool Get(const std::string&, int16_t&) = 0; + virtual bool Get(const std::string&, int32_t&) = 0; + virtual bool Get(const std::string&, int64_t&) = 0; + virtual bool Get(const std::string&, float&) = 0; + virtual bool Get(const std::string&, double&) = 0; + virtual bool Get(const std::string&, Timestamp&) = 0; + virtual bool Get(const std::string&, Date&) = 0; + virtual bool Get(const std::string&, Time&) = 0; + virtual bool Get(const std::string&, DBKey&) = 0; + virtual bool Get(const std::string&, Blob&) = 0; + virtual bool Get(const std::string&, Array&) = 0; + + virtual int ColumnNum(const std::string&) = 0; + virtual const char* ColumnName(int) = 0; + virtual const char* ColumnAlias(int) = 0; + virtual const char* ColumnTable(int) = 0; + virtual SDT ColumnType(int) = 0; + virtual int ColumnSubtype(int) = 0; + virtual int ColumnSize(int) = 0; + virtual int ColumnScale(int) = 0; + virtual int Columns() = 0; + + virtual bool ColumnUpdated(int) = 0; + virtual bool Updated() = 0; + + virtual Database DatabasePtr() const = 0; + virtual Transaction TransactionPtr() const = 0; + + virtual IRow* Clone() = 0; + virtual IRow* AddRef() = 0; + virtual void Release() = 0; + + virtual ~IRow() {} + }; + + /* IStatement is the interface to the statements execution in IBPP. + * Statement is the object class you actually use in your programming. A + * Statement object is the work horse of IBPP. All your data manipulation + * statements will be done through it. It is also used to access the result + * set of a query (when the statement is such), one row at a time and in + * strict forward direction. */ + + class IStatement + { + public: + virtual void Prepare(const std::string&) = 0; + virtual void Execute() = 0; + virtual void Execute(const std::string&) = 0; + virtual void ExecuteImmediate(const std::string&) = 0; + virtual void CursorExecute(const std::string& cursor) = 0; + virtual void CursorExecute(const std::string& cursor, const std::string&) = 0; + virtual bool Fetch() = 0; + virtual bool Fetch(Row&) = 0; + virtual int AffectedRows() = 0; + virtual void Close() = 0; + virtual std::string& Sql() = 0; + virtual STT Type() = 0; + + virtual void SetNull(int) = 0; + virtual void Set(int, bool) = 0; + virtual void Set(int, const void*, int) = 0; // byte buffers + virtual void Set(int, const char*) = 0; // c-string + virtual void Set(int, const std::string&) = 0; + virtual void Set(int, int16_t value) = 0; + virtual void Set(int, int32_t value) = 0; + virtual void Set(int, int64_t value) = 0; + virtual void Set(int, float value) = 0; + virtual void Set(int, double value) = 0; + virtual void Set(int, const Timestamp& value) = 0; + virtual void Set(int, const Date& value) = 0; + virtual void Set(int, const Time& value) = 0; + virtual void Set(int, const DBKey& value) = 0; + virtual void Set(int, const Blob& value) = 0; + virtual void Set(int, const Array& value) = 0; + + virtual bool IsNull(int) = 0; + virtual bool Get(int, bool&) = 0; + virtual bool Get(int, void*, int&) = 0; // byte buffers + virtual bool Get(int, std::string&) = 0; + virtual bool Get(int, int16_t&) = 0; + virtual bool Get(int, int32_t&) = 0; + virtual bool Get(int, int64_t&) = 0; + virtual bool Get(int, float&) = 0; + virtual bool Get(int, double&) = 0; + virtual bool Get(int, Timestamp& value) = 0; + virtual bool Get(int, Date& value) = 0; + virtual bool Get(int, Time& value) = 0; + virtual bool Get(int, DBKey& value) = 0; + virtual bool Get(int, Blob& value) = 0; + virtual bool Get(int, Array& value) = 0; + + virtual bool IsNull(const std::string&) = 0; + virtual bool Get(const std::string&, bool&) = 0; + virtual bool Get(const std::string&, void*, int&) = 0; // byte buffers + virtual bool Get(const std::string&, std::string&) = 0; + virtual bool Get(const std::string&, int16_t&) = 0; + virtual bool Get(const std::string&, int32_t&) = 0; + virtual bool Get(const std::string&, int64_t&) = 0; + virtual bool Get(const std::string&, float&) = 0; + virtual bool Get(const std::string&, double&) = 0; + virtual bool Get(const std::string&, Timestamp& value) = 0; + virtual bool Get(const std::string&, Date& value) = 0; + virtual bool Get(const std::string&, Time& value) = 0; + virtual bool Get(const std::string&, DBKey& value) = 0; + virtual bool Get(const std::string&, Blob& value) = 0; + virtual bool Get(const std::string&, Array& value) = 0; + + virtual int ColumnNum(const std::string&) = 0; + virtual const char* ColumnName(int) = 0; + virtual const char* ColumnAlias(int) = 0; + virtual const char* ColumnTable(int) = 0; + virtual SDT ColumnType(int) = 0; + virtual int ColumnSubtype(int) = 0; + virtual int ColumnSize(int) = 0; + virtual int ColumnScale(int) = 0; + virtual int Columns() = 0; + + virtual SDT ParameterType(int) = 0; + virtual int ParameterSubtype(int) = 0; + virtual int ParameterSize(int) = 0; + virtual int ParameterScale(int) = 0; + virtual int Parameters() = 0; + + virtual void Plan(std::string&) = 0; + + virtual Database DatabasePtr() const = 0; + virtual Transaction TransactionPtr() const = 0; + + virtual IStatement* AddRef() = 0; + virtual void Release() = 0; + + virtual ~IStatement() { } + + // DEPRECATED METHODS (WON'T BE AVAILABLE IN VERSIONS 3.x) + virtual bool Get(int, char*) = 0; // DEPRECATED + virtual bool Get(const std::string&, char*) = 0; // DEPRECATED + virtual bool Get(int, bool*) = 0; // DEPRECATED + virtual bool Get(const std::string&, bool*) = 0; // DEPRECATED + virtual bool Get(int, int16_t*) = 0; // DEPRECATED + virtual bool Get(const std::string&, int16_t*) = 0; // DEPRECATED + virtual bool Get(int, int32_t*) = 0; // DEPRECATED + virtual bool Get(const std::string&, int32_t*) = 0; // DEPRECATED + virtual bool Get(int, int64_t*) = 0; // DEPRECATED + virtual bool Get(const std::string&, int64_t*) = 0; // DEPRECATED + virtual bool Get(int, float*) = 0; // DEPRECATED + virtual bool Get(const std::string&, float*) = 0; // DEPRECATED + virtual bool Get(int, double*) = 0; // DEPRECATED + virtual bool Get(const std::string&, double*) = 0; // DEPRECATED + }; + + class IEvents + { + public: + virtual void Add(const std::string&, EventInterface*) = 0; + virtual void Drop(const std::string&) = 0; + virtual void List(std::vector&) = 0; + virtual void Clear() = 0; // Drop all events + virtual void Dispatch() = 0; // Dispatch events (calls handlers) + + virtual Database DatabasePtr() const = 0; + + virtual IEvents* AddRef() = 0; + virtual void Release() = 0; + + virtual ~IEvents() { } + }; + + /* Class EventInterface is merely a pure interface. + * It is _not_ implemented by IBPP. It is only a base class definition from + * which your own event interface classes have to derive from. + * Please read the reference guide at http://www.ibpp.org for more info. */ + + class EventInterface + { + public: + virtual void ibppEventHandler(Events, const std::string&, int) = 0; + virtual ~EventInterface() { } + }; + + // --- Factories --- + // These methods are the only way to get one of the above + // Interfaces. They are at the heart of how you program using IBPP. For + // instance, to get access to a database, you'll write code similar to this: + // { + // Database db = DatabaseFactory("server", "databasename", + // "user", "password"); + // db->Connect(); + // ... + // db->Disconnect(); + // } + + Service ServiceFactory(const std::string& ServerName, + const std::string& UserName, const std::string& UserPassword); + + Database DatabaseFactory(const std::string& ServerName, + const std::string& DatabaseName, const std::string& UserName, + const std::string& UserPassword, const std::string& RoleName, + const std::string& CharSet, const std::string& CreateParams); + + inline Database DatabaseFactory(const std::string& ServerName, + const std::string& DatabaseName, const std::string& UserName, + const std::string& UserPassword) + { return DatabaseFactory(ServerName, DatabaseName, UserName, UserPassword, "", "", ""); } + + Transaction TransactionFactory(Database db, TAM am = amWrite, + TIL il = ilConcurrency, TLR lr = lrWait, TFF flags = TFF(0)); + + Statement StatementFactory(Database db, Transaction tr, + const std::string& sql); + + inline Statement StatementFactory(Database db, Transaction tr) + { return StatementFactory(db, tr, ""); } + + Blob BlobFactory(Database db, Transaction tr); + + Array ArrayFactory(Database db, Transaction tr); + + Events EventsFactory(Database db); + + /* IBPP uses a self initialization system. Each time an object that may + * require the usage of the Interbase client C-API library is used, the + * library internal handling details are automatically initialized, if not + * already done. You can kick this initialization at the start of an + * application by calling IBPP::CheckVersion(). This is recommended, because + * IBPP::CheckVersion will assure you that YOUR code has been compiled + * against a compatible version of the library. */ + + bool CheckVersion(uint32_t); + int GDSVersion(); + + /* On Win32 platform, ClientLibSearchPaths() allows to setup + * one or multiple additional paths (separated with a ';') where IBPP + * will look for the client library (before the default implicit search + * locations). This is usefull for applications distributed with a 'private' + * copy of Firebird, when the registry is useless to identify the location + * from where to attempt loading the fbclient.dll / gds32.dll. + * If called, this function must be called *early* by the application, + * before *any* other function or object methods of IBPP. + * Currently, this is a NO-OP on platforms other than Win32. */ + + void ClientLibSearchPaths(const std::string&); + + /* Finally, here are some date and time conversion routines used by IBPP and + * that may be helpful at the application level. They do not depend on + * anything related to Firebird/Interbase. Just a bonus. dtoi and itod + * return false on invalid parameters or out of range conversions. */ + + bool dtoi(int date, int* py, int* pm, int* pd); + bool itod(int* pdate, int year, int month, int day); + void ttoi(int itime, int* phour, int* pminute, int* psecond, int* ptt); + void itot(int* ptime, int hour, int minute, int second = 0, int tenthousandths = 0); + +} + +#endif + +// +// EOF +// diff --git a/libs/ibpp/row.cpp b/libs/ibpp/row.cpp new file mode 100644 index 00000000..fa6939ad --- /dev/null +++ b/libs/ibpp/row.cpp @@ -0,0 +1,1580 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: row.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $ +// Subject : IBPP, Row class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include +#include +#include + +using namespace ibpp_internals; + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void RowImpl::SetNull(int param) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::SetNull", _("The row is not initialized.")); + if (param < 1 || param > mDescrArea->sqld) + throw LogicExceptionImpl("Row::SetNull", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[param-1]); + if (! (var->sqltype & 1)) + throw LogicExceptionImpl("Row::SetNull", _("This column can't be null.")); + + *var->sqlind = -1; // Set the column to SQL NULL + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, bool value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[bool]", _("The row is not initialized.")); + + SetValue(param, ivBool, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const char* cstring) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[char*]", _("The row is not initialized.")); + if (cstring == 0) + throw LogicExceptionImpl("Row::Set[char*]", _("null char* pointer detected.")); + + SetValue(param, ivByte, cstring, (int)strlen(cstring)); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const void* bindata, int len) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[void*]", _("The row is not initialized.")); + if (bindata == 0) + throw LogicExceptionImpl("Row::Set[void*]", _("null char* pointer detected.")); + if (len < 0) + throw LogicExceptionImpl("Row::Set[void*]", _("Length must be >= 0")); + + SetValue(param, ivByte, bindata, len); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const std::string& s) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[string]", _("The row is not initialized.")); + + SetValue(param, ivString, (void*)&s); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, int16_t value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[int16_t]", _("The row is not initialized.")); + + SetValue(param, ivInt16, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, int32_t value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[int32_t]", _("The row is not initialized.")); + + SetValue(param, ivInt32, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, int64_t value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[int64_t]", _("The row is not initialized.")); + + SetValue(param, ivInt64, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, float value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[float]", _("The row is not initialized.")); + + SetValue(param, ivFloat, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, double value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[double]", _("The row is not initialized.")); + + SetValue(param, ivDouble, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const IBPP::Timestamp& value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[Timestamp]", _("The row is not initialized.")); + + SetValue(param, ivTimestamp, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const IBPP::Date& value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[Date]", _("The row is not initialized.")); + + if (mDialect == 1) + { + // In dialect 1, IBPP::Date is supposed to work with old 'DATE' + // fields which are actually ISC_TIMESTAMP. + IBPP::Timestamp timestamp(value); + SetValue(param, ivTimestamp, ×tamp); + } + else + { + // Dialect 3 + SetValue(param, ivDate, (void*)&value); + } + + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const IBPP::Time& value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[Time]", _("The row is not initialized.")); + if (mDialect == 1) + throw LogicExceptionImpl("Row::Set[Time]", _("Requires use of a dialect 3 database.")); + + SetValue(param, ivTime, &value); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const IBPP::Blob& blob) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[Blob]", _("The row is not initialized.")); + if (mDatabase != 0 && blob->DatabasePtr() != mDatabase) + throw LogicExceptionImpl("Row::Set[Blob]", + _("IBlob and Row attached to different databases")); + if (mTransaction != 0 && blob->TransactionPtr() != mTransaction) + throw LogicExceptionImpl("Row::Set[Blob]", + _("IBlob and Row attached to different transactions")); + + SetValue(param, ivBlob, blob.intf()); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const IBPP::Array& array) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[Array]", _("The row is not initialized.")); + if (mDatabase != 0 && array->DatabasePtr() != mDatabase) + throw LogicExceptionImpl("Row::Set[Array]", + _("IArray and Row attached to different databases")); + if (mTransaction != 0 && array->TransactionPtr() != mTransaction) + throw LogicExceptionImpl("Row::Set[Array]", + _("IArray and Row attached to different transactions")); + + SetValue(param, ivArray, (void*)array.intf()); + mUpdated[param-1] = true; +} + +void RowImpl::Set(int param, const IBPP::DBKey& key) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[DBKey]", _("The row is not initialized.")); + + SetValue(param, ivDBKey, (void*)&key); + mUpdated[param-1] = true; +} + +/* +void RowImpl::Set(int param, const IBPP::Value& value) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Set[Value]", _("The row is not initialized.")); + + //SetValue(param, ivDBKey, (void*)&key); + //mUpdated[param-1] = true; +} +*/ + +bool RowImpl::IsNull(int column) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized.")); + if (column < 1 || column > mDescrArea->sqld) + throw LogicExceptionImpl("Row::IsNull", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[column-1]); + return ((var->sqltype & 1) && *(var->sqlind) != 0) ? true : false; +} + +bool RowImpl::Get(int column, bool& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivBool); + if (pvalue != 0) + retvalue = (*(char*)pvalue == 0 ? false : true); + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, char* retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Row::Get", _("Null pointer detected")); + + int sqllen; + void* pvalue = GetValue(column, ivByte, &sqllen); + if (pvalue != 0) + { + memcpy(retvalue, pvalue, sqllen); + retvalue[sqllen] = '\0'; + } + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, void* bindata, int& userlen) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + if (bindata == 0) + throw LogicExceptionImpl("Row::Get", _("Null pointer detected")); + if (userlen < 0) + throw LogicExceptionImpl("Row::Get", _("Length must be >= 0")); + + int sqllen; + void* pvalue = GetValue(column, ivByte, &sqllen); + if (pvalue != 0) + { + // userlen says how much bytes the user can accept + // let's shorten it, if there is less bytes available + if (sqllen < userlen) userlen = sqllen; + memcpy(bindata, pvalue, userlen); + } + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, std::string& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivString, &retvalue); + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, int16_t& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivInt16); + if (pvalue != 0) + retvalue = *(int16_t*)pvalue; + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, int32_t& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivInt32); + if (pvalue != 0) + retvalue = *(int32_t*)pvalue; + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, int64_t& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivInt64); + if (pvalue != 0) + retvalue = *(int64_t*)pvalue; + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, float& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivFloat); + if (pvalue != 0) + retvalue = *(float*)pvalue; + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, double& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivDouble); + if (pvalue != 0) + retvalue = *(double*)pvalue; + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, IBPP::Timestamp& timestamp) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp); + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, IBPP::Date& date) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + if (mDialect == 1) + { + // Dialect 1. IBPP::Date is supposed to work with old 'DATE' + // fields which are actually ISC_TIMESTAMP. + IBPP::Timestamp timestamp; + void* pvalue = GetValue(column, ivTimestamp, (void*)×tamp); + if (pvalue != 0) date = timestamp; + return pvalue == 0 ? true : false; + } + else + { + void* pvalue = GetValue(column, ivDate, (void*)&date); + return pvalue == 0 ? true : false; + } +} + +bool RowImpl::Get(int column, IBPP::Time& time) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivTime, (void*)&time); + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, IBPP::Blob& retblob) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivBlob, (void*)retblob.intf()); + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, IBPP::DBKey& retkey) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivDBKey, (void*)&retkey); + return pvalue == 0 ? true : false; +} + +bool RowImpl::Get(int column, IBPP::Array& retarray) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + void* pvalue = GetValue(column, ivArray, (void*)retarray.intf()); + return pvalue == 0 ? true : false; +} + +/* +const IBPP::Value RowImpl::Get(int column) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + //void* value = GetValue(column, ivArray, (void*)retarray.intf()); + //return value == 0 ? true : false; + return IBPP::Value(); +} +*/ + +bool RowImpl::IsNull(const std::string& name) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::IsNull", _("The row is not initialized.")); + + return IsNull(ColumnNum(name)); +} + +bool RowImpl::Get(const std::string& name, bool& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, char* retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get[char*]", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, void* retvalue, int& count) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get[void*,int]", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue, count); +} + +bool RowImpl::Get(const std::string& name, std::string& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::GetString", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, int16_t& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, int32_t& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, int64_t& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, float& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, double& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, IBPP::Timestamp& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, IBPP::Date& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, IBPP::Time& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string&name, IBPP::Blob& retblob) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retblob); +} + +bool RowImpl::Get(const std::string& name, IBPP::DBKey& retvalue) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retvalue); +} + +bool RowImpl::Get(const std::string& name, IBPP::Array& retarray) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name), retarray); +} + +/* +const IBPP::Value RowImpl::Get(const std::string& name) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Get", _("The row is not initialized.")); + + return Get(ColumnNum(name)); +} +*/ + +int RowImpl::Columns() +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::Columns", _("The row is not initialized.")); + + return mDescrArea->sqld; +} + +int RowImpl::ColumnNum(const std::string& name) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnNum", _("The row is not initialized.")); + if (name.empty()) + throw LogicExceptionImpl("Row::ColumnNum", _("Column name not found.")); + + XSQLVAR* var; + char Uname[sizeof(var->sqlname)+1]; // Max size of sqlname + '\0' + + // Local upper case copy of the column name + size_t len = name.length(); + if (len > sizeof(var->sqlname)) len = sizeof(var->sqlname); + strncpy(Uname, name.c_str(), len); + Uname[len] = '\0'; + char* p = Uname; + while (*p != '\0') { *p = char(toupper(*p)); ++p; } + + // Loop through the columns of the descriptor + for (int i = 0; i < mDescrArea->sqld; i++) + { + var = &(mDescrArea->sqlvar[i]); + if (var->sqlname_length != (int16_t)len) continue; + if (strncmp(Uname, var->sqlname, len) == 0) return i+1; + } + + // Failed finding the column name, let's retry using the aliases + char Ualias[sizeof(var->aliasname)+1]; // Max size of aliasname + '\0' + + // Local upper case copy of the column name + len = name.length(); + if (len > sizeof(var->aliasname)) len = sizeof(var->aliasname); + strncpy(Ualias, name.c_str(), len); + Ualias[len] = '\0'; + p = Ualias; + while (*p != '\0') { *p = char(toupper(*p)); ++p; } + + // Loop through the columns of the descriptor + for (int i = 0; i < mDescrArea->sqld; i++) + { + var = &(mDescrArea->sqlvar[i]); + if (var->aliasname_length != (int16_t)len) continue; + if (strncmp(Ualias, var->aliasname, len) == 0) return i+1; + } + + throw LogicExceptionImpl("Row::ColumnNum", _("Could not find matching column.")); +#ifdef __DMC__ + return 0; // DMC errronously warns here about a missing return +#endif +} + +/* +ColumnName, ColumnAlias, ColumnTable : all these 3 have a mistake. +Ideally, the strings should be stored elsewhere (like _Numerics and so on) to +take into account the final '\0' which needs to be added. For now, we insert +the '\0' in the original data, which will cut the 32th character. Not terribly +bad, but should be cleanly rewritten. +*/ + +const char* RowImpl::ColumnName(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnName", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumName", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + if (var->sqlname_length >= 31) var->sqlname_length = 31; + var->sqlname[var->sqlname_length] = '\0'; + return var->sqlname; +} + +const char* RowImpl::ColumnAlias(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnAlias", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumnAlias", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + if (var->aliasname_length >= 31) var->aliasname_length = 31; + var->aliasname[var->aliasname_length] = '\0'; + return var->aliasname; +} + +const char* RowImpl::ColumnTable(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnTable", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumnTable", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + if (var->relname_length >= 31) var->relname_length = 31; + var->relname[var->relname_length] = '\0'; + return var->relname; +} + +IBPP::SDT RowImpl::ColumnType(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnType", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumnType", _("Variable index out of range.")); + + IBPP::SDT value; + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + + switch (var->sqltype & ~1) + { + case SQL_TEXT : value = IBPP::sdString; break; + case SQL_VARYING : value = IBPP::sdString; break; + case SQL_SHORT : value = IBPP::sdSmallint; break; + case SQL_LONG : value = IBPP::sdInteger; break; + case SQL_INT64 : value = IBPP::sdLargeint; break; + case SQL_FLOAT : value = IBPP::sdFloat; break; + case SQL_DOUBLE : value = IBPP::sdDouble; break; + case SQL_TIMESTAMP : value = IBPP::sdTimestamp; break; + case SQL_TYPE_DATE : value = IBPP::sdDate; break; + case SQL_TYPE_TIME : value = IBPP::sdTime; break; + case SQL_BLOB : value = IBPP::sdBlob; break; + case SQL_ARRAY : value = IBPP::sdArray; break; + default : throw LogicExceptionImpl("Row::ColumnType", + _("Found an unknown sqltype !")); + } + + return value; +} + +int RowImpl::ColumnSubtype(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnSubtype", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumnSubtype", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + return (int)var->sqlsubtype; +} + +int RowImpl::ColumnSize(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnSize", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumnSize", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + return var->sqllen; +} + +int RowImpl::ColumnScale(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnScale", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumnScale", _("Variable index out of range.")); + + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + return -var->sqlscale; +} + +bool RowImpl::ColumnUpdated(int varnum) +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized.")); + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("Row::ColumnUpdated", _("Variable index out of range.")); + + return mUpdated[varnum-1]; +} + +bool RowImpl::Updated() +{ + if (mDescrArea == 0) + throw LogicExceptionImpl("Row::ColumnUpdated", _("The row is not initialized.")); + + for (int i = 0; i < mDescrArea->sqld; i++) + if (mUpdated[i]) return true; + return false; +} + +IBPP::Database RowImpl::DatabasePtr() const +{ + return mDatabase; +} + +IBPP::Transaction RowImpl::TransactionPtr() const +{ + return mTransaction; +} + +IBPP::IRow* RowImpl::Clone() +{ + // By definition the clone of an IBPP Row is a new row (so refcount=0). + + RowImpl* clone = new RowImpl(*this); + return clone; +} + +IBPP::IRow* RowImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + return this; +} + +void RowImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void RowImpl::SetValue(int varnum, IITYPE ivType, const void* value, int userlen) +{ + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("RowImpl::SetValue", _("Variable index out of range.")); + if (value == 0) + throw LogicExceptionImpl("RowImpl::SetValue", _("Unexpected null pointer detected.")); + + int16_t len; + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + switch (var->sqltype & ~1) + { + case SQL_TEXT : + if (ivType == ivString) + { + std::string* svalue = (std::string*)value; + len = (int16_t)svalue->length(); + if (len > var->sqllen) len = var->sqllen; + strncpy(var->sqldata, svalue->c_str(), len); + while (len < var->sqllen) var->sqldata[len++] = ' '; + } + else if (ivType == ivByte) + { + if (userlen > var->sqllen) userlen = var->sqllen; + memcpy(var->sqldata, value, userlen); + while (userlen < var->sqllen) var->sqldata[userlen++] = ' '; + } + else if (ivType == ivDBKey) + { + IBPP::DBKey* key = (IBPP::DBKey*)value; + key->GetKey(var->sqldata, var->sqllen); + } + else if (ivType == ivBool) + { + var->sqldata[0] = *(bool*)value ? 'T' : 'F'; + len = 1; + while (len < var->sqllen) var->sqldata[len++] = ' '; + } + else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_VARYING : + if (ivType == ivString) + { + std::string* svalue = (std::string*)value; + len = (int16_t)svalue->length(); + if (len > var->sqllen) len = var->sqllen; + *(int16_t*)var->sqldata = (int16_t)len; + strncpy(var->sqldata+2, svalue->c_str(), len); + } + else if (ivType == ivByte) + { + if (userlen > var->sqllen) userlen = var->sqllen; + *(int16_t*)var->sqldata = (int16_t)userlen; + memcpy(var->sqldata+2, value, userlen); + } + else if (ivType == ivBool) + { + *(int16_t*)var->sqldata = (int16_t)1; + var->sqldata[2] = *(bool*)value ? 'T' : 'F'; + } + else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_SHORT : + if (ivType == ivBool) + { + *(int16_t*)var->sqldata = int16_t(*(bool*)value ? 1 : 0); + } + else if (ivType == ivInt16) + { + *(int16_t*)var->sqldata = *(int16_t*)value; + } + else if (ivType == ivInt32) + { + if (*(int32_t*)value < consts::min16 || *(int32_t*)value > consts::max16) + throw LogicExceptionImpl("RowImpl::SetValue", + _("Out of range numeric conversion !")); + *(int16_t*)var->sqldata = (int16_t)*(int32_t*)value; + } + else if (ivType == ivInt64) + { + if (*(int64_t*)value < consts::min16 || *(int64_t*)value > consts::max16) + throw LogicExceptionImpl("RowImpl::SetValue", + _("Out of range numeric conversion !")); + *(int16_t*)var->sqldata = (int16_t)*(int64_t*)value; + } + else if (ivType == ivFloat) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-var->sqlscale]; + *(int16_t*)var->sqldata = + (int16_t)floor(*(float*)value * multiplier + 0.5); + } + else if (ivType == ivDouble) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-var->sqlscale]; + *(int16_t*)var->sqldata = + (int16_t)floor(*(double*)value * multiplier + 0.5); + } + else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_LONG : + if (ivType == ivBool) + { + *(ISC_LONG*)var->sqldata = *(bool*)value ? 1 : 0; + } + else if (ivType == ivInt16) + { + *(ISC_LONG*)var->sqldata = *(int16_t*)value; + } + else if (ivType == ivInt32) + { + *(ISC_LONG*)var->sqldata = *(ISC_LONG*)value; + } + else if (ivType == ivInt64) + { + if (*(int64_t*)value < consts::min32 || *(int64_t*)value > consts::max32) + throw LogicExceptionImpl("RowImpl::SetValue", + _("Out of range numeric conversion !")); + *(ISC_LONG*)var->sqldata = (ISC_LONG)*(int64_t*)value; + } + else if (ivType == ivFloat) + { + // This SQL_LONG is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-var->sqlscale]; + *(ISC_LONG*)var->sqldata = + (ISC_LONG)floor(*(float*)value * multiplier + 0.5); + } + else if (ivType == ivDouble) + { + // This SQL_LONG is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-var->sqlscale]; + *(ISC_LONG*)var->sqldata = + (ISC_LONG)floor(*(double*)value * multiplier + 0.5); + } + else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_INT64 : + if (ivType == ivBool) + { + *(int64_t*)var->sqldata = *(bool*)value ? 1 : 0; + } + else if (ivType == ivInt16) + { + *(int64_t*)var->sqldata = *(int16_t*)value; + } + else if (ivType == ivInt32) + { + *(int64_t*)var->sqldata = *(int32_t*)value; + } + else if (ivType == ivInt64) + { + *(int64_t*)var->sqldata = *(int64_t*)value; + } + else if (ivType == ivFloat) + { + // This SQL_INT64 is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-var->sqlscale]; + *(int64_t*)var->sqldata = + (int64_t)floor(*(float*)value * multiplier + 0.5); + } + else if (ivType == ivDouble) + { + // This SQL_INT64 is a NUMERIC(x,y), scale it ! + double multiplier = consts::dscales[-var->sqlscale]; + *(int64_t*)var->sqldata = + (int64_t)floor(*(double*)value * multiplier + 0.5); + } + else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_FLOAT : + if (ivType != ivFloat || var->sqlscale != 0) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + *(float*)var->sqldata = *(float*)value; + break; + + case SQL_DOUBLE : + if (ivType != ivDouble) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + if (var->sqlscale != 0) + { + // Round to scale of NUMERIC(x,y) + double multiplier = consts::dscales[-var->sqlscale]; + *(double*)var->sqldata = + floor(*(double*)value * multiplier + 0.5) / multiplier; + } + else *(double*)var->sqldata = *(double*)value; + break; + + case SQL_TIMESTAMP : + if (ivType != ivTimestamp) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + encodeTimestamp(*(ISC_TIMESTAMP*)var->sqldata, *(IBPP::Timestamp*)value); + break; + + case SQL_TYPE_DATE : + if (ivType != ivDate) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + encodeDate(*(ISC_DATE*)var->sqldata, *(IBPP::Date*)value); + break; + + case SQL_TYPE_TIME : + if (ivType != ivTime) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + encodeTime(*(ISC_TIME*)var->sqldata, *(IBPP::Time*)value); + break; + + case SQL_BLOB : + if (ivType == ivBlob) + { + BlobImpl* blob = (BlobImpl*)value; + blob->GetId((ISC_QUAD*)var->sqldata); + } + else if (ivType == ivString) + { + BlobImpl blob(mDatabase, mTransaction); + blob.Save(*(std::string*)value); + blob.GetId((ISC_QUAD*)var->sqldata); + } + else throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_ARRAY : + if (ivType != ivArray) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + { + ArrayImpl* array = (ArrayImpl*)value; + array->GetId((ISC_QUAD*)var->sqldata); + // When an array has been affected to a column, we want to reset + // its ID. This way, the next WriteFrom() on the same Array object + // will allocate a new ID. This protects against storing the same + // array ID in multiple columns or rows. + array->ResetId(); + } + break; + + default : throw LogicExceptionImpl("RowImpl::SetValue", + _("The field uses an unsupported SQL type !")); + } + + if (var->sqltype & 1) *var->sqlind = 0; // Remove the 0 flag +} + +void* RowImpl::GetValue(int varnum, IITYPE ivType, void* retvalue) +{ + if (varnum < 1 || varnum > mDescrArea->sqld) + throw LogicExceptionImpl("RowImpl::GetValue", _("Variable index out of range.")); + + void* value; + int len; + XSQLVAR* var = &(mDescrArea->sqlvar[varnum-1]); + + // When there is no value (SQL NULL) + if ((var->sqltype & 1) && *(var->sqlind) != 0) return 0; + + switch (var->sqltype & ~1) + { + case SQL_TEXT : + if (ivType == ivString) + { + // In case of ivString, 'void* retvalue' points to a std::string where we + // will directly store the data. + std::string* str = (std::string*)retvalue; + str->erase(); + str->append(var->sqldata, var->sqllen); + value = retvalue; // value != 0 means 'not null' + } + else if (ivType == ivByte) + { + // In case of ivByte, void* retvalue points to an int where we + // will store the len of the available data + if (retvalue != 0) *(int*)retvalue = var->sqllen; + value = var->sqldata; + } + else if (ivType == ivDBKey) + { + IBPP::DBKey* key = (IBPP::DBKey*)retvalue; + key->SetKey(var->sqldata, var->sqllen); + value = retvalue; + } + else if (ivType == ivBool) + { + mBools[varnum-1] = 0; + if (var->sqllen >= 1) + { + char c = var->sqldata[0]; + if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1') + mBools[varnum-1] = 1; + } + value = &mBools[varnum-1]; + } + else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_VARYING : + if (ivType == ivString) + { + // In case of ivString, 'void* retvalue' points to a std::string where we + // will directly store the data. + std::string* str = (std::string*)retvalue; + str->erase(); + str->append(var->sqldata+2, (int32_t)*(int16_t*)var->sqldata); + value = retvalue; + } + else if (ivType == ivByte) + { + // In case of ivByte, void* retvalue points to an int where we + // will store the len of the available data + if (retvalue != 0) *(int*)retvalue = (int)*(int16_t*)var->sqldata; + value = var->sqldata+2; + } + else if (ivType == ivBool) + { + mBools[varnum-1] = 0; + len = *(int16_t*)var->sqldata; + if (len >= 1) + { + char c = var->sqldata[2]; + if (c == 't' || c == 'T' || c == 'y' || c == 'Y' || c == '1') + mBools[varnum-1] = 1; + } + value = &mBools[varnum-1]; + } + else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_SHORT : + if (ivType == ivInt16) + { + value = var->sqldata; + } + else if (ivType == ivBool) + { + if (*(int16_t*)var->sqldata == 0) mBools[varnum-1] = 0; + else mBools[varnum-1] = 1; + value = &mBools[varnum-1]; + } + else if (ivType == ivInt32) + { + mInt32s[varnum-1] = *(int16_t*)var->sqldata; + value = &mInt32s[varnum-1]; + } + else if (ivType == ivInt64) + { + mInt64s[varnum-1] = *(int16_t*)var->sqldata; + value = &mInt64s[varnum-1]; + } + else if (ivType == ivFloat) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-var->sqlscale]; + mFloats[varnum-1] = (float)(*(int16_t*)var->sqldata / divisor); + + value = &mFloats[varnum-1]; + } + else if (ivType == ivDouble) + { + // This SQL_SHORT is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-var->sqlscale]; + mNumerics[varnum-1] = *(int16_t*)var->sqldata / divisor; + value = &mNumerics[varnum-1]; + } + else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_LONG : + if (ivType == ivInt32) + { + value = var->sqldata; + } + else if (ivType == ivBool) + { + if (*(int32_t*)var->sqldata == 0) mBools[varnum-1] = 0; + else mBools[varnum-1] = 1; + value = &mBools[varnum-1]; + } + else if (ivType == ivInt16) + { + int32_t tmp = *(int32_t*)var->sqldata; + if (tmp < consts::min16 || tmp > consts::max16) + throw LogicExceptionImpl("RowImpl::GetValue", + _("Out of range numeric conversion !")); + mInt16s[varnum-1] = (int16_t)tmp; + value = &mInt16s[varnum-1]; + } + else if (ivType == ivInt64) + { + mInt64s[varnum-1] = *(int32_t*)var->sqldata; + value = &mInt64s[varnum-1]; + } + else if (ivType == ivFloat) + { + // This SQL_LONG is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-var->sqlscale]; + mFloats[varnum-1] = (float)(*(int32_t*)var->sqldata / divisor); + value = &mFloats[varnum-1]; + } + else if (ivType == ivDouble) + { + // This SQL_LONG is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-var->sqlscale]; + mNumerics[varnum-1] = *(int32_t*)var->sqldata / divisor; + value = &mNumerics[varnum-1]; + } + else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_INT64 : + if (ivType == ivInt64) + { + value = var->sqldata; + } + else if (ivType == ivBool) + { + if (*(int64_t*)var->sqldata == 0) mBools[varnum-1] = 0; + else mBools[varnum-1] = 1; + value = &mBools[varnum-1]; + } + else if (ivType == ivInt16) + { + int64_t tmp = *(int64_t*)var->sqldata; + if (tmp < consts::min16 || tmp > consts::max16) + throw LogicExceptionImpl("RowImpl::GetValue", + _("Out of range numeric conversion !")); + mInt16s[varnum-1] = (int16_t)tmp; + value = &mInt16s[varnum-1]; + } + else if (ivType == ivInt32) + { + int64_t tmp = *(int64_t*)var->sqldata; + if (tmp < consts::min32 || tmp > consts::max32) + throw LogicExceptionImpl("RowImpl::GetValue", + _("Out of range numeric conversion !")); + mInt32s[varnum-1] = (int32_t)tmp; + value = &mInt32s[varnum-1]; + } + else if (ivType == ivFloat) + { + // This SQL_INT64 is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-var->sqlscale]; + mFloats[varnum-1] = (float)(*(int64_t*)var->sqldata / divisor); + value = &mFloats[varnum-1]; + } + else if (ivType == ivDouble) + { + // This SQL_INT64 is a NUMERIC(x,y), scale it ! + double divisor = consts::dscales[-var->sqlscale]; + mNumerics[varnum-1] = *(int64_t*)var->sqldata / divisor; + value = &mNumerics[varnum-1]; + } + else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_FLOAT : + if (ivType != ivFloat) + throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + value = var->sqldata; + break; + + case SQL_DOUBLE : + if (ivType != ivDouble) + throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + if (var->sqlscale != 0) + { + // Round to scale y of NUMERIC(x,y) + double multiplier = consts::dscales[-var->sqlscale]; + mNumerics[varnum-1] = + floor(*(double*)var->sqldata * multiplier + 0.5) / multiplier; + value = &mNumerics[varnum-1]; + } + else value = var->sqldata; + break; + + case SQL_TIMESTAMP : + if (ivType != ivTimestamp) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + decodeTimestamp(*(IBPP::Timestamp*)retvalue, *(ISC_TIMESTAMP*)var->sqldata); + value = retvalue; + break; + + case SQL_TYPE_DATE : + if (ivType != ivDate) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + decodeDate(*(IBPP::Date*)retvalue, *(ISC_DATE*)var->sqldata); + value = retvalue; + break; + + case SQL_TYPE_TIME : + if (ivType != ivTime) + throw WrongTypeImpl("RowImpl::SetValue", var->sqltype, ivType, + _("Incompatible types.")); + decodeTime(*(IBPP::Time*)retvalue, *(ISC_TIME*)var->sqldata); + value = retvalue; + break; + + case SQL_BLOB : + if (ivType == ivBlob) + { + BlobImpl* blob = (BlobImpl*)retvalue; + blob->SetId((ISC_QUAD*)var->sqldata); + value = retvalue; + } + else if (ivType == ivString) + { + BlobImpl blob(mDatabase, mTransaction); + blob.SetId((ISC_QUAD*)var->sqldata); + std::string* str = (std::string*)retvalue; + blob.Load(*str); + value = retvalue; + } + else throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + break; + + case SQL_ARRAY : + if (ivType != ivArray) + throw WrongTypeImpl("RowImpl::GetValue", var->sqltype, ivType, + _("Incompatible types.")); + { + ArrayImpl* array = (ArrayImpl*)retvalue; + array->SetId((ISC_QUAD*)var->sqldata); + value = retvalue; + } + break; + + default : throw LogicExceptionImpl("RowImpl::GetValue", + _("Found an unknown sqltype !")); + } + + return value; +} + +void RowImpl::Free() +{ + if (mDescrArea != 0) + { + for (int i = 0; i < mDescrArea->sqln; i++) + { + XSQLVAR* var = &(mDescrArea->sqlvar[i]); + if (var->sqldata != 0) + { + switch (var->sqltype & ~1) + { + case SQL_ARRAY : + case SQL_BLOB : delete (ISC_QUAD*) var->sqldata; break; + case SQL_TIMESTAMP :delete (ISC_TIMESTAMP*) var->sqldata; break; + case SQL_TYPE_TIME :delete (ISC_TIME*) var->sqldata; break; + case SQL_TYPE_DATE :delete (ISC_DATE*) var->sqldata; break; + case SQL_TEXT : + case SQL_VARYING : delete [] var->sqldata; break; + case SQL_SHORT : delete (int16_t*) var->sqldata; break; + case SQL_LONG : delete (int32_t*) var->sqldata; break; + case SQL_INT64 : delete (int64_t*) var->sqldata; break; + case SQL_FLOAT : delete (float*) var->sqldata; break; + case SQL_DOUBLE : delete (double*) var->sqldata; break; + default : throw LogicExceptionImpl("RowImpl::Free", + _("Found an unknown sqltype !")); + } + } + if (var->sqlind != 0) delete var->sqlind; + } + delete [] (char*)mDescrArea; + mDescrArea = 0; + } + + mNumerics.clear(); + mFloats.clear(); + mInt64s.clear(); + mInt32s.clear(); + mInt16s.clear(); + mBools.clear(); + mStrings.clear(); + mUpdated.clear(); + + mDialect = 0; + mDatabase = 0; + mTransaction = 0; +} + +void RowImpl::Resize(int n) +{ + const int size = XSQLDA_LENGTH(n); + + Free(); + mDescrArea = (XSQLDA*) new char[size]; + + memset(mDescrArea, 0, size); + mNumerics.resize(n); + mFloats.resize(n); + mInt64s.resize(n); + mInt32s.resize(n); + mInt16s.resize(n); + mBools.resize(n); + mStrings.resize(n); + mUpdated.resize(n); + for (int i = 0; i < n; i++) + { + mNumerics[i] = 0.0; + mFloats[i] = 0.0; + mInt64s[i] = 0; + mInt32s[i] = 0; + mInt16s[i] = 0; + mBools[i] = 0; + mStrings[i].erase(); + mUpdated[i] = false; + } + + mDescrArea->version = SQLDA_VERSION1; + mDescrArea->sqln = (int16_t)n; +} + +void RowImpl::AllocVariables() +{ + int i; + for (i = 0; i < mDescrArea->sqld; i++) + { + XSQLVAR* var = &(mDescrArea->sqlvar[i]); + switch (var->sqltype & ~1) + { + case SQL_ARRAY : + case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD; + memset(var->sqldata, 0, sizeof(ISC_QUAD)); + break; + case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP; + memset(var->sqldata, 0, sizeof(ISC_TIMESTAMP)); + break; + case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME; + memset(var->sqldata, 0, sizeof(ISC_TIME)); + break; + case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE; + memset(var->sqldata, 0, sizeof(ISC_DATE)); + break; + case SQL_TEXT : var->sqldata = new char[var->sqllen+1]; + memset(var->sqldata, ' ', var->sqllen); + var->sqldata[var->sqllen] = '\0'; + break; + case SQL_VARYING : var->sqldata = new char[var->sqllen+3]; + memset(var->sqldata, 0, 2); + memset(var->sqldata+2, ' ', var->sqllen); + var->sqldata[var->sqllen+2] = '\0'; + break; + case SQL_SHORT : var->sqldata = (char*) new int16_t(0); break; + case SQL_LONG : var->sqldata = (char*) new int32_t(0); break; + case SQL_INT64 : var->sqldata = (char*) new int64_t(0); break; + case SQL_FLOAT : var->sqldata = (char*) new float(0.0); break; + case SQL_DOUBLE : var->sqldata = (char*) new double(0.0); break; + default : throw LogicExceptionImpl("RowImpl::AllocVariables", + _("Found an unknown sqltype !")); + } + if (var->sqltype & 1) var->sqlind = new short(-1); // 0 indicator + } +} + +bool RowImpl::MissingValues() +{ + for (int i = 0; i < mDescrArea->sqld; i++) + if (! mUpdated[i]) return true; + return false; +} + +RowImpl& RowImpl::operator=(const RowImpl& copied) +{ + Free(); + + const int n = copied.mDescrArea->sqln; + const int size = XSQLDA_LENGTH(n); + + // Initial brute copy + mDescrArea = (XSQLDA*) new char[size]; + memcpy(mDescrArea, copied.mDescrArea, size); + + // Copy of the columns data + for (int i = 0; i < mDescrArea->sqld; i++) + { + XSQLVAR* var = &(mDescrArea->sqlvar[i]); + XSQLVAR* org = &(copied.mDescrArea->sqlvar[i]); + switch (var->sqltype & ~1) + { + case SQL_ARRAY : + case SQL_BLOB : var->sqldata = (char*) new ISC_QUAD; + memcpy(var->sqldata, org->sqldata, sizeof(ISC_QUAD)); + break; + case SQL_TIMESTAMP :var->sqldata = (char*) new ISC_TIMESTAMP; + memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIMESTAMP)); + break; + case SQL_TYPE_TIME :var->sqldata = (char*) new ISC_TIME; + memcpy(var->sqldata, org->sqldata, sizeof(ISC_TIME)); + break; + case SQL_TYPE_DATE :var->sqldata = (char*) new ISC_DATE; + memcpy(var->sqldata, org->sqldata, sizeof(ISC_DATE)); + break; + case SQL_TEXT : var->sqldata = new char[var->sqllen+1]; + memcpy(var->sqldata, org->sqldata, var->sqllen+1); + break; + case SQL_VARYING : var->sqldata = new char[var->sqllen+3]; + memcpy(var->sqldata, org->sqldata, var->sqllen+3); + break; + case SQL_SHORT : var->sqldata = (char*) new int16_t(*(int16_t*)org->sqldata); break; + case SQL_LONG : var->sqldata = (char*) new int32_t(*(int32_t*)org->sqldata); break; + case SQL_INT64 : var->sqldata = (char*) new int64_t(*(int64_t*)org->sqldata); break; + case SQL_FLOAT : var->sqldata = (char*) new float(*(float*)org->sqldata); break; + case SQL_DOUBLE : var->sqldata = (char*) new double(*(double*)org->sqldata); break; + default : throw LogicExceptionImpl("RowImpl::Ctor", + _("Found an unknown sqltype !")); + } + if (var->sqltype & 1) var->sqlind = new short(*org->sqlind); // 0 indicator + } + + // Pointers init, real data copy + mNumerics = copied.mNumerics; + mFloats = copied.mFloats; + mInt64s = copied.mInt64s; + mInt32s = copied.mInt32s; + mInt16s = copied.mInt16s; + mBools = copied.mBools; + mStrings = copied.mStrings; + + mDialect = copied.mDialect; + mDatabase = copied.mDatabase; + mTransaction = copied.mTransaction; + + return *this; +} + +RowImpl::RowImpl(const RowImpl& copied) + : IBPP::IRow(), mRefCount(0), mDescrArea(0) +{ + // mRefCount and mDescrArea are set to 0 before using the assignment operator + *this = copied; // The assignment operator does the real copy +} + +RowImpl::RowImpl(int dialect, int n, DatabaseImpl* db, TransactionImpl* tr) + : mRefCount(0), mDescrArea(0) +{ + Resize(n); + mDialect = dialect; + mDatabase = db; + mTransaction = tr; +} + +RowImpl::~RowImpl() +{ + try { Free(); } + catch (...) { } +} + +// +// EOF +// diff --git a/libs/ibpp/service.cpp b/libs/ibpp/service.cpp new file mode 100644 index 00000000..26726ea1 --- /dev/null +++ b/libs/ibpp/service.cpp @@ -0,0 +1,774 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: service.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $ +// Subject : IBPP, Service class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +using namespace ibpp_internals; + +#ifdef IBPP_UNIX +#include +#define Sleep(x) usleep(x) +#endif + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void ServiceImpl::Connect() +{ + if (mHandle != 0) return; // Already connected + + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mUserName.empty()) + throw LogicExceptionImpl("Service::Connect", _("Unspecified user name.")); + if (mUserPassword.empty()) + throw LogicExceptionImpl("Service::Connect", _("Unspecified user password.")); + + // Attach to the Service Manager + IBS status; + SPB spb; + std::string connect; + + // Build a SPB based on the properties + spb.Insert(isc_spb_version); + spb.Insert(isc_spb_current_version); + spb.InsertString(isc_spb_user_name, 1, mUserName.c_str()); + spb.InsertString(isc_spb_password, 1, mUserPassword.c_str()); + + if (! mServerName.empty()) + { + connect = mServerName; + connect += ":"; + } + + connect += "service_mgr"; + + (*gds.Call()->m_service_attach)(status.Self(), (short)connect.size(), (char*)connect.c_str(), + &mHandle, spb.Size(), spb.Self()); + if (status.Errors()) + { + mHandle = 0; // Should be, but better be sure... + throw SQLExceptionImpl(status, "Service::Connect", _("isc_service_attach failed")); + } +} + +void ServiceImpl::Disconnect() +{ + if (mHandle == 0) return; // Already disconnected + + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + + IBS status; + + // Detach from the service manager + (*gds.Call()->m_service_detach)(status.Self(), &mHandle); + + // Set mHandle to 0 now, just in case we need to throw, because Disconnect() + // is called from Service destructor and we want to maintain a coherent state. + mHandle = 0; + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::Disconnect", _("isc_service_detach failed")); +} + +void ServiceImpl::GetVersion(std::string& version) +{ + // Based on a patch provided by Torsten Martinsen (SourceForge 'bullestock') + + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::GetVersion", _("Service is not connected.")); + + IBS status; + SPB spb; + RB result(250); + + spb.Insert(isc_info_svc_server_version); + + (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, spb.Size(), spb.Self(), + result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::GetVersion", _("isc_service_query failed")); + + result.GetString(isc_info_svc_server_version, version); +} + +void ServiceImpl::AddUser(const IBPP::User& user) +{ + if (gds.Call()->mGDSVersion >= 60 && mHandle == 0) + throw LogicExceptionImpl("Service::AddUser", _("Service is not connected.")); + if (user.username.empty()) + throw LogicExceptionImpl("Service::AddUser", _("Username required.")); + if (user.password.empty()) + throw LogicExceptionImpl("Service::AddUser", _("Password required.")); + + IBS status; + SPB spb; + spb.Insert(isc_action_svc_add_user); + spb.InsertString(isc_spb_sec_username, 2, user.username.c_str()); + spb.InsertString(isc_spb_sec_password, 2, user.password.c_str()); + if (! user.firstname.empty()) + spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str()); + if (! user.middlename.empty()) + spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str()); + if (! user.lastname.empty()) + spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str()); + if (user.userid != 0) + spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid); + if (user.groupid != 0) + spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::AddUser", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::ModifyUser(const IBPP::User& user) +{ + if (gds.Call()->mGDSVersion >= 60 && mHandle == 0) + throw LogicExceptionImpl("Service::ModifyUser", _("Service is not connected.")); + if (user.username.empty()) + throw LogicExceptionImpl("Service::ModifyUser", _("Username required.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_modify_user); + spb.InsertString(isc_spb_sec_username, 2, user.username.c_str()); + if (! user.password.empty()) + spb.InsertString(isc_spb_sec_password, 2, user.password.c_str()); + if (! user.firstname.empty()) + spb.InsertString(isc_spb_sec_firstname, 2, user.firstname.c_str()); + if (! user.middlename.empty()) + spb.InsertString(isc_spb_sec_middlename, 2, user.middlename.c_str()); + if (! user.lastname.empty()) + spb.InsertString(isc_spb_sec_lastname, 2, user.lastname.c_str()); + if (user.userid != 0) + spb.InsertQuad(isc_spb_sec_userid, (int32_t)user.userid); + if (user.groupid != 0) + spb.InsertQuad(isc_spb_sec_groupid, (int32_t)user.groupid); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::ModifyUser", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::RemoveUser(const std::string& username) +{ + + if (gds.Call()->mGDSVersion >= 60 && mHandle == 0) + throw LogicExceptionImpl("Service::RemoveUser", _("Service is not connected.")); + if (username.empty()) + throw LogicExceptionImpl("Service::RemoveUser", _("Username required.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_delete_user); + spb.InsertString(isc_spb_sec_username, 2, username.c_str()); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::RemoveUser", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::GetUser(IBPP::User& user) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::GetUser", _("Service is not connected.")); + if (user.username.empty()) + throw LogicExceptionImpl("Service::GetUser", _("Username required.")); + + SPB spb; + spb.Insert(isc_action_svc_display_user); + spb.InsertString(isc_spb_sec_username, 2, user.username.c_str()); + + IBS status; + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_start failed")); + + RB result(8000); + char request[] = {isc_info_svc_get_users}; + status.Reset(); + (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, + sizeof(request), request, result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query failed")); + + char* p = result.Self(); + if (*p != isc_info_svc_get_users) + throw SQLExceptionImpl(status, "Service::GetUser", _("isc_service_query returned unexpected answer")); + + p += 3; // Skips the 'isc_info_svc_get_users' and its total length + user.clear(); + while (*p != isc_info_end) + { + if (*p == isc_spb_sec_userid) + { + user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4); + p += 5; + } + else if (*p == isc_spb_sec_groupid) + { + user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4); + p += 5; + } + else + { + unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2); + switch (*p) + { + case isc_spb_sec_username : + // For each user, this is the first element returned + if (len != 0) user.username.assign(p+3, len); + break; + case isc_spb_sec_password : + if (len != 0) user.password.assign(p+3, len); + break; + case isc_spb_sec_firstname : + if (len != 0) user.firstname.assign(p+3, len); + break; + case isc_spb_sec_middlename : + if (len != 0) user.middlename.assign(p+3, len); + break; + case isc_spb_sec_lastname : + if (len != 0) user.lastname.assign(p+3, len); + break; + } + p += (3 + len); + } + } +} + +void ServiceImpl::GetUsers(std::vector& users) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::GetUsers", _("Service is not connected.")); + + SPB spb; + spb.Insert(isc_action_svc_display_user); + + IBS status; + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_start failed")); + + RB result(8000); + char request[] = {isc_info_svc_get_users}; + status.Reset(); + (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, + sizeof(request), request, result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query failed")); + + users.clear(); + char* p = result.Self(); + if (*p != isc_info_svc_get_users) + throw SQLExceptionImpl(status, "Service::GetUsers", _("isc_service_query returned unexpected answer")); + + p += 3; // Skips the 'isc_info_svc_get_users' and its total length + IBPP::User user; + while (*p != isc_info_end) + { + if (*p == isc_spb_sec_userid) + { + user.userid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4); + p += 5; + } + else if (*p == isc_spb_sec_groupid) + { + user.groupid = (uint32_t)(*gds.Call()->m_vax_integer)(p+1, 4); + p += 5; + } + else + { + unsigned short len = (unsigned short)(*gds.Call()->m_vax_integer)(p+1, 2); + switch (*p) + { + case isc_spb_sec_username : + // For each user, this is the first element returned + if (! user.username.empty()) users.push_back(user); // Flush previous user + user.clear(); + if (len != 0) user.username.assign(p+3, len); + break; + case isc_spb_sec_password : + if (len != 0) user.password.assign(p+3, len); + break; + case isc_spb_sec_firstname : + if (len != 0) user.firstname.assign(p+3, len); + break; + case isc_spb_sec_middlename : + if (len != 0) user.middlename.assign(p+3, len); + break; + case isc_spb_sec_lastname : + if (len != 0) user.lastname.assign(p+3, len); + break; + } + p += (3 + len); + } + } + if (! user.username.empty()) users.push_back(user); // Flush last user +} + +void ServiceImpl::SetPageBuffers(const std::string& dbfile, int buffers) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::SetPageBuffers", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::SetPageBuffers", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_properties); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + spb.InsertQuad(isc_spb_prp_page_buffers, buffers); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::SetPageBuffers", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::SetSweepInterval(const std::string& dbfile, int sweep) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::SetSweepInterval", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::SetSweepInterval", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_properties); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + spb.InsertQuad(isc_spb_prp_sweep_interval, sweep); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::SetSweepInterval", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::SetSyncWrite(const std::string& dbfile, bool sync) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::SetSyncWrite", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::SetSyncWrite", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_properties); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + if (sync) spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_sync); + else spb.InsertByte(isc_spb_prp_write_mode, (char)isc_spb_prp_wm_async); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::SetSyncWrite", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::SetReadOnly(const std::string& dbfile, bool readonly) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::SetReadOnly", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::SetReadOnly", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_properties); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + if (readonly) spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readonly); + else spb.InsertByte(isc_spb_prp_access_mode, (char)isc_spb_prp_am_readwrite); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::SetReadOnly", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::SetReserveSpace(const std::string& dbfile, bool reserve) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::SetReserveSpace", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::SetReserveSpace", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_properties); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + if (reserve) spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res); + else spb.InsertByte(isc_spb_prp_reserve_space, (char)isc_spb_prp_res_use_full); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::SetReserveSpace", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::Shutdown(const std::string& dbfile, IBPP::DSM mode, int sectimeout) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::Shutdown", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::Shutdown", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_properties); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + switch (mode) + { + case IBPP::dsDenyAttach : + spb.InsertQuad(isc_spb_prp_deny_new_attachments, sectimeout); + break; + case IBPP::dsDenyTrans : + spb.InsertQuad(isc_spb_prp_deny_new_transactions, sectimeout); + break; + case IBPP::dsForce : + spb.InsertQuad(isc_spb_prp_shutdown_db, sectimeout); + break; + } + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::Shutdown", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::Restart(const std::string& dbfile) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::Restart", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::Restart", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_properties); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + spb.InsertQuad(isc_spb_options, isc_spb_prp_db_online); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::Restart", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::Sweep(const std::string& dbfile) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::Sweep", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::Sweep", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_repair); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + spb.InsertQuad(isc_spb_options, isc_spb_rpr_sweep_db); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::Sweep", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::Repair(const std::string& dbfile, IBPP::RPF flags) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::Repair", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::Repair", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_repair); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + + unsigned int mask; + if (flags & IBPP::rpValidateFull) mask = (isc_spb_rpr_full | isc_spb_rpr_validate_db); + else if (flags & IBPP::rpValidatePages) mask = isc_spb_rpr_validate_db; + else if (flags & IBPP::rpMendRecords) mask = isc_spb_rpr_mend_db; + else throw LogicExceptionImpl("Service::Repair", + _("One of rpMendRecords, rpValidatePages, rpValidateFull is required.")); + + if (flags & IBPP::rpReadOnly) mask |= isc_spb_rpr_check_db; + if (flags & IBPP::rpIgnoreChecksums) mask |= isc_spb_rpr_ignore_checksum; + if (flags & IBPP::rpKillShadows) mask |= isc_spb_rpr_kill_shadows; + + spb.InsertQuad(isc_spb_options, mask); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::Repair", _("isc_service_start failed")); + + Wait(); +} + +void ServiceImpl::StartBackup(const std::string& dbfile, + const std::string& bkfile, IBPP::BRF flags) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::Backup", _("Service is not connected.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::Backup", _("Main database file must be specified.")); + if (bkfile.empty()) + throw LogicExceptionImpl("Service::Backup", _("Backup file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_backup); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str()); + if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose); + + unsigned int mask = 0; + if (flags & IBPP::brIgnoreChecksums) mask |= isc_spb_bkp_ignore_checksums; + if (flags & IBPP::brIgnoreLimbo) mask |= isc_spb_bkp_ignore_limbo; + if (flags & IBPP::brMetadataOnly) mask |= isc_spb_bkp_metadata_only; + if (flags & IBPP::brNoGarbageCollect) mask |= isc_spb_bkp_no_garbage_collect; + if (flags & IBPP::brNonTransportable) mask |= isc_spb_bkp_non_transportable; + if (flags & IBPP::brConvertExtTables) mask |= isc_spb_bkp_convert; + if (mask != 0) spb.InsertQuad(isc_spb_options, mask); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::Backup", _("isc_service_start failed")); +} + +void ServiceImpl::StartRestore(const std::string& bkfile, const std::string& dbfile, + int pagesize, IBPP::BRF flags) +{ + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + if (mHandle == 0) + throw LogicExceptionImpl("Service::Restore", _("Service is not connected.")); + if (bkfile.empty()) + throw LogicExceptionImpl("Service::Restore", _("Backup file must be specified.")); + if (dbfile.empty()) + throw LogicExceptionImpl("Service::Restore", _("Main database file must be specified.")); + + IBS status; + SPB spb; + + spb.Insert(isc_action_svc_restore); + spb.InsertString(isc_spb_bkp_file, 2, bkfile.c_str()); + spb.InsertString(isc_spb_dbname, 2, dbfile.c_str()); + if (flags & IBPP::brVerbose) spb.Insert(isc_spb_verbose); + if (pagesize != 0) spb.InsertQuad(isc_spb_res_page_size, pagesize); + + unsigned int mask; + if (flags & IBPP::brReplace) mask = isc_spb_res_replace; + else mask = isc_spb_res_create; // Safe default mode + + if (flags & IBPP::brDeactivateIdx) mask |= isc_spb_res_deactivate_idx; + if (flags & IBPP::brNoShadow) mask |= isc_spb_res_no_shadow; + if (flags & IBPP::brNoValidity) mask |= isc_spb_res_no_validity; + if (flags & IBPP::brPerTableCommit) mask |= isc_spb_res_one_at_a_time; + if (flags & IBPP::brUseAllSpace) mask |= isc_spb_res_use_all_space; + if (mask != 0) spb.InsertQuad(isc_spb_options, mask); + + (*gds.Call()->m_service_start)(status.Self(), &mHandle, 0, spb.Size(), spb.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "Service::Restore", _("isc_service_start failed")); +} + +const char* ServiceImpl::WaitMsg() +{ + IBS status; + SPB req; + RB result(1024); + + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + + req.Insert(isc_info_svc_line); // Request one line of textual output + + // _service_query will only block until a line of result is available + // (or until the end of the task if it does not report information) + (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, + req.Size(), req.Self(), result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed")); + + // If message length is zero bytes, task is finished + if (result.GetString(isc_info_svc_line, mWaitMessage) == 0) return 0; + + // Task is not finished, but we have something to report + return mWaitMessage.c_str(); +} + +void ServiceImpl::Wait() +{ + IBS status; + SPB spb; + RB result(1024); + std::string msg; + + if (gds.Call()->mGDSVersion < 60) + throw LogicExceptionImpl("Service", _("Requires the version 6 of GDS32.DLL")); + + spb.Insert(isc_info_svc_line); + for (;;) + { + // Sleeps 1 millisecond upfront. This will release the remaining + // timeslot of the thread. Doing so will give a good chance for small + // services tasks to finish before we check if they are still running. + // The deal is to limit (in that particular case) the number of loops + // polling _service_query that will happen. + + Sleep(1); + + // _service_query will only block until a line of result is available + // (or until the end of the task if it does not report information) + (*gds.Call()->m_service_query)(status.Self(), &mHandle, 0, 0, 0, + spb.Size(), spb.Self(), result.Size(), result.Self()); + if (status.Errors()) + throw SQLExceptionImpl(status, "ServiceImpl::Wait", _("isc_service_query failed")); + + // If message length is zero bytes, task is finished + if (result.GetString(isc_info_svc_line, msg) == 0) return; + + status.Reset(); + result.Reset(); + } +} + +IBPP::IService* ServiceImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + return this; +} + +void ServiceImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void ServiceImpl::SetServerName(const char* newName) +{ + if (newName == 0) mServerName.erase(); + else mServerName = newName; +} + +void ServiceImpl::SetUserName(const char* newName) +{ + if (newName == 0) mUserName.erase(); + else mUserName = newName; +} + +void ServiceImpl::SetUserPassword(const char* newPassword) +{ + if (newPassword == 0) mUserPassword.erase(); + else mUserPassword = newPassword; +} + +ServiceImpl::ServiceImpl(const std::string& ServerName, + const std::string& UserName, const std::string& UserPassword) + : mRefCount(0), mHandle(0), + mServerName(ServerName), mUserName(UserName), mUserPassword(UserPassword) +{ +} + +ServiceImpl::~ServiceImpl() +{ + try { if (Connected()) Disconnect(); } + catch (...) { } +} + +// +// Eof +// diff --git a/libs/ibpp/statement.cpp b/libs/ibpp/statement.cpp new file mode 100644 index 00000000..e2271cf4 --- /dev/null +++ b/libs/ibpp/statement.cpp @@ -0,0 +1,1307 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: statement.cpp,v 1.2 2009/03/19 20:00:28 faust Exp $ +// Subject : IBPP, Service class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void StatementImpl::Prepare(const std::string& sql) +{ + if (mDatabase == 0) + throw LogicExceptionImpl("Statement::Prepare", _("An IDatabase must be attached.")); + if (mDatabase->GetHandle() == 0) + throw LogicExceptionImpl("Statement::Prepare", _("IDatabase must be connected.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Statement::Prepare", _("An ITransaction must be attached.")); + if (mTransaction->GetHandle() == 0) + throw LogicExceptionImpl("Statement::Prepare", _("ITransaction must be started.")); + if (sql.empty()) + throw LogicExceptionImpl("Statement::Prepare", _("SQL statement can't be 0.")); + + // Saves the SQL sentence, only for reporting reasons in case of errors + mSql = sql; + + IBS status; + + // Free all resources currently attached to this Statement, then allocate + // a new statement descriptor. + Close(); + (*gds.Call()->m_dsql_allocate_statement)(status.Self(), mDatabase->GetHandlePtr(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Statement::Prepare", + _("isc_dsql_allocate_statement failed")); + + // Empirical estimate of parameters count and output columns count. + // This is by far not an exact estimation, which would require parsing the + // SQL statement. If the SQL statement contains '?' and ',' in string + // constants, this count will obviously be wrong, but it will be exagerated. + // It won't hurt. We just try to not have to re-allocate those descriptors later. + // So we prefer to get them a little bit larger than needed than the other way. + int16_t inEstimate = 0; + int16_t outEstimate = 1; + for (size_t i = 0; i < strlen(sql.c_str()); i++) + { + if (sql[i] == '?') ++inEstimate; + if (sql[i] == ',') ++outEstimate; + } + + /* + DebugStream()<< "Prepare(\""<< sql<< "\")"<< fds; + DebugStream()<< _("Estimation: ")<< inEstimate<< _(" IN parameters and ") + << outEstimate<< _(" OUT columns")<< fds; + */ + + // Allocates output descriptor and prepares the statement + mOutRow = new RowImpl(mDatabase->Dialect(), outEstimate, mDatabase, mTransaction); + mOutRow->AddRef(); + + status.Reset(); + (*gds.Call()->m_dsql_prepare)(status.Self(), mTransaction->GetHandlePtr(), + &mHandle, (short)sql.length(), const_cast(sql.c_str()), + short(mDatabase->Dialect()), mOutRow->Self()); + if (status.Errors()) + { + Close(); + std::string context = "Statement::Prepare( "; + context.append(mSql).append(" )"); + throw SQLExceptionImpl(status, context.c_str(), + _("isc_dsql_prepare failed")); + } + + // Read what kind of statement was prepared + status.Reset(); + char itemsReq[] = {isc_info_sql_stmt_type}; + char itemsRes[8]; + (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq, + sizeof(itemsRes), itemsRes); + if (status.Errors()) + { + Close(); + throw SQLExceptionImpl(status, "Statement::Prepare", + _("isc_dsql_sql_info failed")); + } + if (itemsRes[0] == isc_info_sql_stmt_type) + { + switch (itemsRes[3]) + { + case isc_info_sql_stmt_select : mType = IBPP::stSelect; break; + case isc_info_sql_stmt_insert : mType = IBPP::stInsert; break; + case isc_info_sql_stmt_update : mType = IBPP::stUpdate; break; + case isc_info_sql_stmt_delete : mType = IBPP::stDelete; break; + case isc_info_sql_stmt_ddl : mType = IBPP::stDDL; break; + case isc_info_sql_stmt_exec_procedure : mType = IBPP::stExecProcedure; break; + case isc_info_sql_stmt_select_for_upd : mType = IBPP::stSelectUpdate; break; + case isc_info_sql_stmt_set_generator : mType = IBPP::stSetGenerator; break; + case isc_info_sql_stmt_savepoint : mType = IBPP::stSavePoint; break; + default : mType = IBPP::stUnsupported; + } + } + if (mType == IBPP::stUnknown || mType == IBPP::stUnsupported) + { + Close(); + throw LogicExceptionImpl("Statement::Prepare", + _("Unknown or unsupported statement type")); + } + + if (mOutRow->Columns() == 0) + { + // Get rid of the output descriptor, if it wasn't required (no output) + mOutRow->Release(); + mOutRow = 0; + /* + DebugStream()<< _("Dropped output descriptor which was not required")<< fds; + */ + } + else if (mOutRow->Columns() > mOutRow->AllocatedSize()) + { + // Resize the output descriptor (which is too small). + // The statement does not need to be prepared again, though the + // output columns must be described again. + + /* + DebugStream()<< _("Resize output descriptor from ") + << mOutRow->AllocatedSize()<< _(" to ")<< mOutRow->Columns()<< fds; + */ + + mOutRow->Resize(mOutRow->Columns()); + status.Reset(); + (*gds.Call()->m_dsql_describe)(status.Self(), &mHandle, 1, mOutRow->Self()); + if (status.Errors()) + { + Close(); + throw SQLExceptionImpl(status, "Statement::Prepare", + _("isc_dsql_describe failed")); + } + } + + if (inEstimate > 0) + { + // Ready an input descriptor + mInRow = new RowImpl(mDatabase->Dialect(), inEstimate, mDatabase, mTransaction); + mInRow->AddRef(); + + status.Reset(); + (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self()); + if (status.Errors()) + { + Close(); + throw SQLExceptionImpl(status, "Statement::Prepare", + _("isc_dsql_describe_bind failed")); + } + + if (mInRow->Columns() == 0) + { + // Get rid of the input descriptor, if it wasn't required (no parameters) + mInRow->Release(); + mInRow = 0; + /* + DebugStream()<< _("Dropped input descriptor which was not required")<< fds; + */ + } + else if (mInRow->Columns() > mInRow->AllocatedSize()) + { + // Resize the input descriptor (which is too small). + // The statement does not need to be prepared again, though the + // parameters must be described again. + + /* + DebugStream()<< _("Resize input descriptor from ") + << mInRow->AllocatedSize()<< _(" to ") + << mInRow->Columns()<< fds; + */ + + mInRow->Resize(mInRow->Columns()); + status.Reset(); + (*gds.Call()->m_dsql_describe_bind)(status.Self(), &mHandle, 1, mInRow->Self()); + if (status.Errors()) + { + Close(); + throw SQLExceptionImpl(status, "Statement::Prepare", + _("isc_dsql_describe_bind failed")); + } + } + } + + // Allocates variables of the input descriptor + if (mInRow != 0) + { + // Turn on 'can be NULL' on each input parameter + for (int i = 0; i < mInRow->Columns(); i++) + { + XSQLVAR* var = &(mInRow->Self()->sqlvar[i]); + if (! (var->sqltype & 1)) var->sqltype += short(1); + } + mInRow->AllocVariables(); + } + + // Allocates variables of the output descriptor + if (mOutRow != 0) mOutRow->AllocVariables(); +} + +void StatementImpl::Plan(std::string& plan) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Plan", _("No statement has been prepared.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Statement::Plan", _("A Database must be attached.")); + if (mDatabase->GetHandle() == 0) + throw LogicExceptionImpl("Statement::Plan", _("Database must be connected.")); + + IBS status; + RB result(4096); + char itemsReq[] = {isc_info_sql_get_plan}; + + (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq, + result.Size(), result.Self()); + if (status.Errors()) throw SQLExceptionImpl(status, + "Statement::Plan", _("isc_dsql_sql_info failed.")); + + result.GetString(isc_info_sql_get_plan, plan); + if (plan[0] == '\n') plan.erase(0, 1); +} + +void StatementImpl::Execute(const std::string& sql) +{ + if (! sql.empty()) Prepare(sql); + + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Execute", + _("No statement has been prepared.")); + + // Check that a value has been set for each input parameter + if (mInRow != 0 && mInRow->MissingValues()) + throw LogicExceptionImpl("Statement::Execute", + _("All parameters must be specified.")); + + CursorFree(); // Free a previous 'cursor' if any + + IBS status; + if (mType == IBPP::stSelect) + { + // Could return a result set (none, single or multi rows) + (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(), + &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self()); + if (status.Errors()) + { + //Close(); Commented because Execute error should not free the statement + std::string context = "Statement::Execute( "; + context.append(mSql).append(" )"); + throw SQLExceptionImpl(status, context.c_str(), + _("isc_dsql_execute failed")); + } + if (mOutRow != 0) + { + mResultSetAvailable = true; + mCursorOpened = true; + } + } + else + { + // Should return at most a single row + (*gds.Call()->m_dsql_execute2)(status.Self(), mTransaction->GetHandlePtr(), + &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self(), + mOutRow == 0 ? 0 : mOutRow->Self()); + if (status.Errors()) + { + //Close(); Commented because Execute error should not free the statement + std::string context = "Statement::Execute( "; + context.append(mSql).append(" )"); + throw SQLExceptionImpl(status, context.c_str(), + _("isc_dsql_execute2 failed")); + } + } +} + +void StatementImpl::CursorExecute(const std::string& cursor, const std::string& sql) +{ + if (cursor.empty()) + throw LogicExceptionImpl("Statement::CursorExecute", _("Cursor name can't be 0.")); + + if (! sql.empty()) Prepare(sql); + + if (mHandle == 0) + throw LogicExceptionImpl("Statement::CursorExecute", _("No statement has been prepared.")); + if (mType != IBPP::stSelectUpdate) + throw LogicExceptionImpl("Statement::CursorExecute", _("Statement must be a SELECT FOR UPDATE.")); + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::CursorExecute", _("Statement would return no rows.")); + + // Check that a value has been set for each input parameter + if (mInRow != 0 && mInRow->MissingValues()) + throw LogicExceptionImpl("Statement::CursorExecute", + _("All parameters must be specified.")); + + CursorFree(); // Free a previous 'cursor' if any + + IBS status; + (*gds.Call()->m_dsql_execute)(status.Self(), mTransaction->GetHandlePtr(), + &mHandle, 1, mInRow == 0 ? 0 : mInRow->Self()); + if (status.Errors()) + { + //Close(); Commented because Execute error should not free the statement + std::string context = "Statement::CursorExecute( "; + context.append(mSql).append(" )"); + throw SQLExceptionImpl(status, context.c_str(), + _("isc_dsql_execute failed")); + } + + status.Reset(); + (*gds.Call()->m_dsql_set_cursor_name)(status.Self(), &mHandle, const_cast(cursor.c_str()), 0); + if (status.Errors()) + { + //Close(); Commented because Execute error should not free the statement + throw SQLExceptionImpl(status, "Statement::CursorExecute", + _("isc_dsql_set_cursor_name failed")); + } + + mResultSetAvailable = true; + mCursorOpened = true; +} + +void StatementImpl::ExecuteImmediate(const std::string& sql) +{ + if (mDatabase == 0) + throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An IDatabase must be attached.")); + if (mDatabase->GetHandle() == 0) + throw LogicExceptionImpl("Statement::ExecuteImmediate", _("IDatabase must be connected.")); + if (mTransaction == 0) + throw LogicExceptionImpl("Statement::ExecuteImmediate", _("An ITransaction must be attached.")); + if (mTransaction->GetHandle() == 0) + throw LogicExceptionImpl("Statement::ExecuteImmediate", _("ITransaction must be started.")); + if (sql.empty()) + throw LogicExceptionImpl("Statement::ExecuteImmediate", _("SQL statement can't be 0.")); + + IBS status; + Close(); + (*gds.Call()->m_dsql_execute_immediate)(status.Self(), mDatabase->GetHandlePtr(), + mTransaction->GetHandlePtr(), 0, const_cast(sql.c_str()), + short(mDatabase->Dialect()), 0); + if (status.Errors()) + { + std::string context = "Statement::ExecuteImmediate( "; + context.append(sql).append(" )"); + throw SQLExceptionImpl(status, context.c_str(), + _("isc_dsql_execute_immediate failed")); + } +} + +int StatementImpl::AffectedRows() +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::AffectedRows", _("No statement has been prepared.")); + if (mDatabase == 0) + throw LogicExceptionImpl("Statement::AffectedRows", _("A Database must be attached.")); + if (mDatabase->GetHandle() == 0) + throw LogicExceptionImpl("Statement::AffectedRows", _("Database must be connected.")); + + int count; + IBS status; + RB result; + char itemsReq[] = {isc_info_sql_records}; + + (*gds.Call()->m_dsql_sql_info)(status.Self(), &mHandle, 1, itemsReq, + result.Size(), result.Self()); + if (status.Errors()) throw SQLExceptionImpl(status, + "Statement::AffectedRows", _("isc_dsql_sql_info failed.")); + + if (mType == IBPP::stInsert) + count = result.GetValue(isc_info_sql_records, isc_info_req_insert_count); + else if (mType == IBPP::stUpdate) + count = result.GetValue(isc_info_sql_records, isc_info_req_update_count); + else if (mType == IBPP::stDelete) + count = result.GetValue(isc_info_sql_records, isc_info_req_delete_count); + else if (mType == IBPP::stSelect) + count = result.GetValue(isc_info_sql_records, isc_info_req_select_count); + else count = 0; // Returns zero count for unknown cases + + return count; +} + +bool StatementImpl::Fetch() +{ + if (! mResultSetAvailable) + throw LogicExceptionImpl("Statement::Fetch", + _("No statement has been executed or no result set available.")); + + IBS status; + ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1, mOutRow->Self()); + if (code == 100) // This special code means "no more rows" + { + mResultSetAvailable = false; + // Oddly enough, fetching rows up to the last one seems to open + // an 'implicit' cursor that needs to be closed. + mCursorOpened = true; + CursorFree(); // Free the explicit or implicit cursor/result-set + return false; + } + if (status.Errors()) + { + Close(); + throw SQLExceptionImpl(status, "Statement::Fetch", + _("isc_dsql_fetch failed.")); + } + + return true; +} + +bool StatementImpl::Fetch(IBPP::Row& row) +{ + if (! mResultSetAvailable) + throw LogicExceptionImpl("Statement::Fetch(row)", + _("No statement has been executed or no result set available.")); + + RowImpl* rowimpl = new RowImpl(*mOutRow); + row = rowimpl; + + IBS status; + ISC_STATUS code = (*gds.Call()->m_dsql_fetch)(status.Self(), &mHandle, 1, + rowimpl->Self()); + if (code == 100) // This special code means "no more rows" + { + mResultSetAvailable = false; + // Oddly enough, fetching rows up to the last one seems to open + // an 'implicit' cursor that needs to be closed. + mCursorOpened = true; + CursorFree(); // Free the explicit or implicit cursor/result-set + row.clear(); + return false; + } + if (status.Errors()) + { + Close(); + row.clear(); + throw SQLExceptionImpl(status, "Statement::Fetch(row)", + _("isc_dsql_fetch failed.")); + } + + return true; +} + +void StatementImpl::Close() +{ + // Free all statement resources. + // Used before preparing a new statement or from destructor. + + if (mInRow != 0) { mInRow->Release(); mInRow = 0; } + if (mOutRow != 0) { mOutRow->Release(); mOutRow = 0; } + + mResultSetAvailable = false; + mCursorOpened = false; + mType = IBPP::stUnknown; + + if (mHandle != 0) + { + IBS status; + (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_drop); + mHandle = 0; + if (status.Errors()) + throw SQLExceptionImpl(status, "Statement::Close(DSQL_drop)", + _("isc_dsql_free_statement failed.")); + } +} + +void StatementImpl::SetNull(int param) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::SetNull", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::SetNull", _("The statement does not take parameters.")); + + mInRow->SetNull(param); +} + +void StatementImpl::Set(int param, bool value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[bool]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[bool]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, const char* cstring) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[char*]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[char*]", _("The statement does not take parameters.")); + + mInRow->Set(param, cstring); +} + +void StatementImpl::Set(int param, const void* bindata, int len) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[void*]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[void*]", _("The statement does not take parameters.")); + + mInRow->Set(param, bindata, len); +} + +void StatementImpl::Set(int param, const std::string& s) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[string]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[string]", _("The statement does not take parameters.")); + + mInRow->Set(param, s); +} + +void StatementImpl::Set(int param, int16_t value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[int16_t]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[int16_t]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, int32_t value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[int32_t]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[int32_t]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, int64_t value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[int64_t]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[int64_t]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, float value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[float]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[float]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, double value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[double]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[double]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, const IBPP::Timestamp& value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[Timestamp]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[Timestamp]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, const IBPP::Date& value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[Date]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[Date]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, const IBPP::Time& value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[Time]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[Time]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} + +void StatementImpl::Set(int param, const IBPP::Blob& blob) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[Blob]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[Blob]", _("The statement does not take parameters.")); + + mInRow->Set(param, blob); +} + +void StatementImpl::Set(int param, const IBPP::Array& array) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[Array]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[Array]", _("The statement does not take parameters.")); + + mInRow->Set(param, array); +} + +void StatementImpl::Set(int param, const IBPP::DBKey& key) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[DBKey]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[DBKey]", _("The statement does not take parameters.")); + + mInRow->Set(param, key); +} + +/* +void StatementImpl::Set(int param, const IBPP::Value& value) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Set[Value]", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Set[Value]", _("The statement does not take parameters.")); + + mInRow->Set(param, value); +} +*/ + +bool StatementImpl::IsNull(int column) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized.")); + + return mOutRow->IsNull(column); +} + +bool StatementImpl::Get(int column, bool* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(column, *retvalue); +} + +bool StatementImpl::Get(int column, bool& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, char* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, void* bindata, int& userlen) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, bindata, userlen); +} + +bool StatementImpl::Get(int column, std::string& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, int16_t* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(column, *retvalue); +} + +bool StatementImpl::Get(int column, int16_t& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, int32_t* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(column, *retvalue); +} + +bool StatementImpl::Get(int column, int32_t& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, int64_t* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(column, *retvalue); +} + +bool StatementImpl::Get(int column, int64_t& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, float* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(column, *retvalue); +} + +bool StatementImpl::Get(int column, float& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, double* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(column, *retvalue); +} + +bool StatementImpl::Get(int column, double& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, retvalue); +} + +bool StatementImpl::Get(int column, IBPP::Timestamp& timestamp) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, timestamp); +} + +bool StatementImpl::Get(int column, IBPP::Date& date) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, date); +} + +bool StatementImpl::Get(int column, IBPP::Time& time) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, time); +} + +bool StatementImpl::Get(int column, IBPP::Blob& blob) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, blob); +} + +bool StatementImpl::Get(int column, IBPP::DBKey& key) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, key); +} + +bool StatementImpl::Get(int column, IBPP::Array& array) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column, array); +} + +/* +const IBPP::Value StatementImpl::Get(int column) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(column); +} +*/ + +bool StatementImpl::IsNull(const std::string& name) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::IsNull", _("The row is not initialized.")); + + return mOutRow->IsNull(name); +} + +bool StatementImpl::Get(const std::string& name, bool* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(name, *retvalue); +} + +bool StatementImpl::Get(const std::string& name, bool& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, char* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get[char*]", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, void* retvalue, int& count) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get[void*,int]", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue, count); +} + +bool StatementImpl::Get(const std::string& name, std::string& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::GetString", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, int16_t* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(name, *retvalue); +} + +bool StatementImpl::Get(const std::string& name, int16_t& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, int32_t* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(name, *retvalue); +} + +bool StatementImpl::Get(const std::string& name, int32_t& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, int64_t* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(name, *retvalue); +} + +bool StatementImpl::Get(const std::string& name, int64_t& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, float* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(name, *retvalue); +} + +bool StatementImpl::Get(const std::string& name, float& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, double* retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + if (retvalue == 0) + throw LogicExceptionImpl("Statement::Get", _("Null pointer detected")); + + return mOutRow->Get(name, *retvalue); +} + +bool StatementImpl::Get(const std::string& name, double& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, IBPP::Timestamp& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, IBPP::Date& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, IBPP::Time& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string&name, IBPP::Blob& retblob) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retblob); +} + +bool StatementImpl::Get(const std::string& name, IBPP::DBKey& retvalue) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retvalue); +} + +bool StatementImpl::Get(const std::string& name, IBPP::Array& retarray) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name, retarray); +} + +/* +const IBPP::Value StatementImpl::Get(const std::string& name) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Get", _("The row is not initialized.")); + + return mOutRow->Get(name); +} +*/ + +int StatementImpl::Columns() +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized.")); + + return mOutRow->Columns(); +} + +int StatementImpl::ColumnNum(const std::string& name) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::ColumnNum", _("The row is not initialized.")); + + return mOutRow->ColumnNum(name); +} + +const char* StatementImpl::ColumnName(int varnum) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized.")); + + return mOutRow->ColumnName(varnum); +} + +const char* StatementImpl::ColumnAlias(int varnum) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized.")); + + return mOutRow->ColumnAlias(varnum); +} + +const char* StatementImpl::ColumnTable(int varnum) +{ + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::Columns", _("The row is not initialized.")); + + return mOutRow->ColumnTable(varnum); +} + +IBPP::SDT StatementImpl::ColumnType(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ColumnType", _("No statement has been prepared.")); + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::ColumnType", _("The statement does not return results.")); + + return mOutRow->ColumnType(varnum); +} + +int StatementImpl::ColumnSubtype(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ColumnSubtype", _("No statement has been prepared.")); + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::ColumnSubtype", _("The statement does not return results.")); + + return mOutRow->ColumnSubtype(varnum); +} + +int StatementImpl::ColumnSize(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ColumnSize", _("No statement has been prepared.")); + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::ColumnSize", _("The row is not initialized.")); + + return mOutRow->ColumnSize(varnum); +} + +int StatementImpl::ColumnScale(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ColumnScale", _("No statement has been prepared.")); + if (mOutRow == 0) + throw LogicExceptionImpl("Statement::ColumnScale", _("The row is not initialized.")); + + return mOutRow->ColumnScale(varnum); +} + +int StatementImpl::Parameters() +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::Parameters", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::Parameters", _("The statement uses no parameters.")); + + return mInRow->Columns(); +} + +IBPP::SDT StatementImpl::ParameterType(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ParameterType", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::ParameterType", _("The statement uses no parameters.")); + + return mInRow->ColumnType(varnum); +} + +int StatementImpl::ParameterSubtype(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ParameterSubtype", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::ParameterSubtype", _("The statement uses no parameters.")); + + return mInRow->ColumnSubtype(varnum); +} + +int StatementImpl::ParameterSize(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ParameterSize", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::ParameterSize", _("The statement uses no parameters.")); + + return mInRow->ColumnSize(varnum); +} + +int StatementImpl::ParameterScale(int varnum) +{ + if (mHandle == 0) + throw LogicExceptionImpl("Statement::ParameterScale", _("No statement has been prepared.")); + if (mInRow == 0) + throw LogicExceptionImpl("Statement::ParameterScale", _("The statement uses no parameters.")); + + return mInRow->ColumnScale(varnum); +} + +IBPP::Database StatementImpl::DatabasePtr() const +{ + return mDatabase; +} + +IBPP::Transaction StatementImpl::TransactionPtr() const +{ + return mTransaction; +} + +IBPP::IStatement* StatementImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + + return this; +} + +void StatementImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void StatementImpl::AttachDatabaseImpl(DatabaseImpl* database) +{ + if (database == 0) + throw LogicExceptionImpl("Statement::AttachDatabase", + _("Can't attach a 0 IDatabase object.")); + + if (mDatabase != 0) mDatabase->DetachStatementImpl(this); + mDatabase = database; + mDatabase->AttachStatementImpl(this); +} + +void StatementImpl::DetachDatabaseImpl() +{ + if (mDatabase == 0) return; + + Close(); + mDatabase->DetachStatementImpl(this); + mDatabase = 0; +} + +void StatementImpl::AttachTransactionImpl(TransactionImpl* transaction) +{ + if (transaction == 0) + throw LogicExceptionImpl("Statement::AttachTransaction", + _("Can't attach a 0 ITransaction object.")); + + if (mTransaction != 0) mTransaction->DetachStatementImpl(this); + mTransaction = transaction; + mTransaction->AttachStatementImpl(this); +} + +void StatementImpl::DetachTransactionImpl() +{ + if (mTransaction == 0) return; + + Close(); + mTransaction->DetachStatementImpl(this); + mTransaction = 0; +} + +void StatementImpl::CursorFree() +{ + if (mCursorOpened) + { + mCursorOpened = false; + if (mHandle != 0) + { + IBS status; + (*gds.Call()->m_dsql_free_statement)(status.Self(), &mHandle, DSQL_close); + if (status.Errors()) + throw SQLExceptionImpl(status, "StatementImpl::CursorFree(DSQL_close)", + _("isc_dsql_free_statement failed.")); + } + } +} + +StatementImpl::StatementImpl(DatabaseImpl* database, TransactionImpl* transaction, + const std::string& sql) + : mRefCount(0), mHandle(0), mDatabase(0), mTransaction(0), + mInRow(0), mOutRow(0), + mResultSetAvailable(false), mCursorOpened(false), mType(IBPP::stUnknown) +{ + AttachDatabaseImpl(database); + if (transaction != 0) AttachTransactionImpl(transaction); + if (! sql.empty()) Prepare(sql); +} + +StatementImpl::~StatementImpl() +{ + try { Close(); } + catch (...) { } + try { if (mTransaction != 0) mTransaction->DetachStatementImpl(this); } + catch (...) { } + try { if (mDatabase != 0) mDatabase->DetachStatementImpl(this); } + catch (...) { } +} + +// +// EOF +// diff --git a/libs/ibpp/time.cpp b/libs/ibpp/time.cpp new file mode 100644 index 00000000..ffdd5f6a --- /dev/null +++ b/libs/ibpp/time.cpp @@ -0,0 +1,208 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: time.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $ +// Subject : IBPP, Time class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include // Can't use thanks to MSVC6 buggy library + +using namespace ibpp_internals; + +void IBPP::Time::Now() +{ + time_t systime = time(0); + tm* loctime = localtime(&systime); + IBPP::itot(&mTime, loctime->tm_hour, loctime->tm_min, loctime->tm_sec, 0); +} + +void IBPP::Time::SetTime(int tm) +{ + if (tm < 0 || tm > 863999999) + throw LogicExceptionImpl("Time::SetTime", _("Invalid time value")); + mTime = tm; +} + +void IBPP::Time::SetTime(int hour, int minute, int second, int tenthousandths) +{ + if (hour < 0 || hour > 23 || + minute < 0 || minute > 59 || + second < 0 || second > 59 || + tenthousandths < 0 || tenthousandths > 9999) + throw LogicExceptionImpl("Time::SetTime", + _("Invalid hour, minute, second values")); + IBPP::itot(&mTime, hour, minute, second, tenthousandths); +} + +void IBPP::Time::GetTime(int& hour, int& minute, int& second) const +{ + IBPP::ttoi(mTime, &hour, &minute, &second, 0); +} + +void IBPP::Time::GetTime(int& hour, int& minute, int& second, int& tenthousandths) const +{ + IBPP::ttoi(mTime, &hour, &minute, &second, &tenthousandths); +} + +int IBPP::Time::Hours() const +{ + int hours; + IBPP::ttoi(mTime, &hours, 0, 0, 0); + return hours; +} + +int IBPP::Time::Minutes() const +{ + int minutes; + IBPP::ttoi(mTime, 0, &minutes, 0, 0); + return minutes; +} + +int IBPP::Time::Seconds() const +{ + int seconds; + IBPP::ttoi(mTime, 0, 0, &seconds, 0); + return seconds; +} + +int IBPP::Time::SubSeconds() const // Actually tenthousandths of seconds +{ + int tenthousandths; + IBPP::ttoi(mTime, 0, 0, 0, &tenthousandths); + return tenthousandths; +} + +IBPP::Time::Time(int hour, int minute, int second, int tenthousandths) +{ + SetTime(hour, minute, second, tenthousandths); +} + +IBPP::Time::Time(const IBPP::Time& copied) +{ + mTime = copied.mTime; +} + +IBPP::Time& IBPP::Time::operator=(const IBPP::Timestamp& assigned) +{ + mTime = assigned.GetTime(); + return *this; +} + +IBPP::Time& IBPP::Time::operator=(const IBPP::Time& assigned) +{ + mTime = assigned.mTime; + return *this; +} + +// Time calculations. Internal format is the number of seconds elapsed since +// midnight. Splits such a time in its hours, minutes, seconds components. + +void IBPP::ttoi(int itime, int *h, int *m, int *s, int* t) +{ + int hh, mm, ss, tt; + + hh = (int) (itime / 36000000); itime = itime - hh * 36000000; + mm = (int) (itime / 600000); itime = itime - mm * 600000; + ss = (int) (itime / 10000); + tt = (int) (itime - ss * 10000); + + if (h != 0) *h = hh; + if (m != 0) *m = mm; + if (s != 0) *s = ss; + if (t != 0) *t = tt; + + return; +} + +// Get the internal time format, given hour, minute, second. + +void IBPP::itot (int *ptime, int hour, int minute, int second, int tenthousandths) +{ + *ptime = hour * 36000000 + minute * 600000 + second * 10000 + tenthousandths; + return; +} + +namespace ibpp_internals +{ + +// +// The following functions are helper conversions functions between IBPP +// Date, Time, Timestamp and ISC_DATE, ISC_TIME and ISC_TIMESTAMP. +// (They must be maintained if the encoding used by Firebird evolve.) +// These helper functions are used from row.cpp and from array.cpp. +// + +void encodeDate(ISC_DATE& isc_dt, const IBPP::Date& dt) +{ + // There simply has a shift of 15019 between the native Firebird + // date model and the IBPP model. + isc_dt = (ISC_DATE)(dt.GetDate() + 15019); +} + +void decodeDate(IBPP::Date& dt, const ISC_DATE& isc_dt) +{ + // There simply has a shift of 15019 between the native Firebird + // date model and the IBPP model. + dt.SetDate((int)isc_dt - 15019); +} + +void encodeTime(ISC_TIME& isc_tm, const IBPP::Time& tm) +{ + isc_tm = (ISC_TIME)tm.GetTime(); +} + +void decodeTime(IBPP::Time& tm, const ISC_TIME& isc_tm) +{ + tm.SetTime((int)isc_tm); +} + +void encodeTimestamp(ISC_TIMESTAMP& isc_ts, const IBPP::Timestamp& ts) +{ + encodeDate(isc_ts.timestamp_date, ts); + encodeTime(isc_ts.timestamp_time, ts); +} + +void decodeTimestamp(IBPP::Timestamp& ts, const ISC_TIMESTAMP& isc_ts) +{ + decodeDate(ts, isc_ts.timestamp_date); + decodeTime(ts, isc_ts.timestamp_time); +} + +} + +// +// EOF +// + diff --git a/libs/ibpp/transaction.cpp b/libs/ibpp/transaction.cpp new file mode 100644 index 00000000..47eb61c7 --- /dev/null +++ b/libs/ibpp/transaction.cpp @@ -0,0 +1,409 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: transaction.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $ +// Subject : IBPP, Database class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include + +using namespace ibpp_internals; + +// (((((((( OBJECT INTERFACE IMPLEMENTATION )))))))) + +void TransactionImpl::AttachDatabase(IBPP::Database db, + IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags) +{ + if (db.intf() == 0) + throw LogicExceptionImpl("Transaction::AttachDatabase", + _("Can't attach an unbound Database.")); + + AttachDatabaseImpl(dynamic_cast(db.intf()), am, il, lr, flags); +} + +void TransactionImpl::DetachDatabase(IBPP::Database db) +{ + if (db.intf() == 0) + throw LogicExceptionImpl("Transaction::DetachDatabase", + _("Can't detach an unbound Database.")); + + DetachDatabaseImpl(dynamic_cast(db.intf())); +} + +void TransactionImpl::AddReservation(IBPP::Database db, + const std::string& table, IBPP::TTR tr) +{ + if (mHandle != 0) + throw LogicExceptionImpl("Transaction::AddReservation", + _("Can't add table reservation if Transaction started.")); + if (db.intf() == 0) + throw LogicExceptionImpl("Transaction::AddReservation", + _("Can't add table reservation on an unbound Database.")); + + // Find the TPB associated with this database + std::vector::iterator pos = + std::find(mDatabases.begin(), mDatabases.end(), dynamic_cast(db.intf())); + if (pos != mDatabases.end()) + { + size_t index = pos - mDatabases.begin(); + TPB* tpb = mTPBs[index]; + + // Now add the reservations to the TPB + switch (tr) + { + case IBPP::trSharedWrite : + tpb->Insert(isc_tpb_lock_write); + tpb->Insert(table); + tpb->Insert(isc_tpb_shared); + break; + case IBPP::trSharedRead : + tpb->Insert(isc_tpb_lock_read); + tpb->Insert(table); + tpb->Insert(isc_tpb_shared); + break; + case IBPP::trProtectedWrite : + tpb->Insert(isc_tpb_lock_write); + tpb->Insert(table); + tpb->Insert(isc_tpb_protected); + break; + case IBPP::trProtectedRead : + tpb->Insert(isc_tpb_lock_read); + tpb->Insert(table); + tpb->Insert(isc_tpb_protected); + break; + /*default : + throw LogicExceptionImpl("Transaction::AddReservation", + _("Illegal TTR value detected."));*/ + } + } + else throw LogicExceptionImpl("Transaction::AddReservation", + _("The database connection you specified is not attached to this transaction.")); +} + +void TransactionImpl::Start() +{ + if (mHandle != 0) return; // Already started anyway + + if (mDatabases.empty()) + throw LogicExceptionImpl("Transaction::Start", _("No Database is attached.")); + + struct ISC_TEB + { + ISC_LONG* db_ptr; + ISC_LONG tpb_len; + char* tpb_ptr; + } * teb = new ISC_TEB[mDatabases.size()]; + + unsigned i; + for (i = 0; i < mDatabases.size(); i++) + { + if (mDatabases[i]->GetHandle() == 0) + { + // All Databases must be connected to Start the transaction ! + delete [] teb; + throw LogicExceptionImpl("Transaction::Start", + _("All attached Database should have been connected.")); + } + teb[i].db_ptr = (ISC_LONG*) mDatabases[i]->GetHandlePtr(); + teb[i].tpb_len = mTPBs[i]->Size(); + teb[i].tpb_ptr = mTPBs[i]->Self(); + } + + IBS status; + (*gds.Call()->m_start_multiple)(status.Self(), &mHandle, (short)mDatabases.size(), teb); + delete [] teb; + if (status.Errors()) + { + mHandle = 0; // Should be, but better be sure... + throw SQLExceptionImpl(status, "Transaction::Start"); + } +} + +void TransactionImpl::Commit() +{ + if (mHandle == 0) + throw LogicExceptionImpl("Transaction::Commit", _("Transaction is not started.")); + + IBS status; + + (*gds.Call()->m_commit_transaction)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Transaction::Commit"); + mHandle = 0; // Should be, better be sure +} + +void TransactionImpl::CommitRetain() +{ + if (mHandle == 0) + throw LogicExceptionImpl("Transaction::CommitRetain", _("Transaction is not started.")); + + IBS status; + + (*gds.Call()->m_commit_retaining)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Transaction::CommitRetain"); +} + +void TransactionImpl::Rollback() +{ + if (mHandle == 0) return; // Transaction not started anyway + + IBS status; + + (*gds.Call()->m_rollback_transaction)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Transaction::Rollback"); + mHandle = 0; // Should be, better be sure +} + +void TransactionImpl::RollbackRetain() +{ + if (mHandle == 0) + throw LogicExceptionImpl("Transaction::RollbackRetain", _("Transaction is not started.")); + + IBS status; + + (*gds.Call()->m_rollback_retaining)(status.Self(), &mHandle); + if (status.Errors()) + throw SQLExceptionImpl(status, "Transaction::RollbackRetain"); +} + +IBPP::ITransaction* TransactionImpl::AddRef() +{ + ASSERTION(mRefCount >= 0); + ++mRefCount; + return this; +} + +void TransactionImpl::Release() +{ + // Release cannot throw, except in DEBUG builds on assertion + ASSERTION(mRefCount >= 0); + --mRefCount; + try { if (mRefCount <= 0) delete this; } + catch (...) { } +} + +// (((((((( OBJECT INTERNAL METHODS )))))))) + +void TransactionImpl::Init() +{ + mHandle = 0; + mDatabases.clear(); + mTPBs.clear(); + mStatements.clear(); + mBlobs.clear(); + mArrays.clear(); +} + +void TransactionImpl::AttachStatementImpl(StatementImpl* st) +{ + if (st == 0) + throw LogicExceptionImpl("Transaction::AttachStatement", + _("Can't attach a 0 Statement object.")); + + mStatements.push_back(st); +} + +void TransactionImpl::DetachStatementImpl(StatementImpl* st) +{ + if (st == 0) + throw LogicExceptionImpl("Transaction::DetachStatement", + _("Can't detach a 0 Statement object.")); + + mStatements.erase(std::find(mStatements.begin(), mStatements.end(), st)); +} + +void TransactionImpl::AttachBlobImpl(BlobImpl* bb) +{ + if (bb == 0) + throw LogicExceptionImpl("Transaction::AttachBlob", + _("Can't attach a 0 BlobImpl object.")); + + mBlobs.push_back(bb); +} + +void TransactionImpl::DetachBlobImpl(BlobImpl* bb) +{ + if (bb == 0) + throw LogicExceptionImpl("Transaction::DetachBlob", + _("Can't detach a 0 BlobImpl object.")); + + mBlobs.erase(std::find(mBlobs.begin(), mBlobs.end(), bb)); +} + +void TransactionImpl::AttachArrayImpl(ArrayImpl* ar) +{ + if (ar == 0) + throw LogicExceptionImpl("Transaction::AttachArray", + _("Can't attach a 0 ArrayImpl object.")); + + mArrays.push_back(ar); +} + +void TransactionImpl::DetachArrayImpl(ArrayImpl* ar) +{ + if (ar == 0) + throw LogicExceptionImpl("Transaction::DetachArray", + _("Can't detach a 0 ArrayImpl object.")); + + mArrays.erase(std::find(mArrays.begin(), mArrays.end(), ar)); +} + +void TransactionImpl::AttachDatabaseImpl(DatabaseImpl* dbi, + IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags) +{ + if (mHandle != 0) + throw LogicExceptionImpl("Transaction::AttachDatabase", + _("Can't attach a Database if Transaction started.")); + if (dbi == 0) + throw LogicExceptionImpl("Transaction::AttachDatabase", + _("Can't attach a null Database.")); + + mDatabases.push_back(dbi); + + // Prepare a new TPB + TPB* tpb = new TPB; + if (am == IBPP::amRead) tpb->Insert(isc_tpb_read); + else tpb->Insert(isc_tpb_write); + + switch (il) + { + case IBPP::ilConsistency : tpb->Insert(isc_tpb_consistency); break; + case IBPP::ilReadDirty : tpb->Insert(isc_tpb_read_committed); + tpb->Insert(isc_tpb_rec_version); break; + case IBPP::ilReadCommitted : tpb->Insert(isc_tpb_read_committed); + tpb->Insert(isc_tpb_no_rec_version); break; + case IBPP::ilConcurrency : tpb->Insert(isc_tpb_concurrency); break; + } + + if (lr == IBPP::lrNoWait) tpb->Insert(isc_tpb_nowait); + else tpb->Insert(isc_tpb_wait); + + if (flags & IBPP::tfIgnoreLimbo) tpb->Insert(isc_tpb_ignore_limbo); + if (flags & IBPP::tfAutoCommit) tpb->Insert(isc_tpb_autocommit); + if (flags & IBPP::tfNoAutoUndo) tpb->Insert(isc_tpb_no_auto_undo); + + mTPBs.push_back(tpb); + + // Signals the Database object that it has been attached to the Transaction + dbi->AttachTransactionImpl(this); +} + +void TransactionImpl::DetachDatabaseImpl(DatabaseImpl* dbi) +{ + if (mHandle != 0) + throw LogicExceptionImpl("Transaction::DetachDatabase", + _("Can't detach a Database if Transaction started.")); + if (dbi == 0) + throw LogicExceptionImpl("Transaction::DetachDatabase", + _("Can't detach a null Database.")); + + std::vector::iterator pos = + std::find(mDatabases.begin(), mDatabases.end(), dbi); + if (pos != mDatabases.end()) + { + size_t index = pos - mDatabases.begin(); + TPB* tpb = mTPBs[index]; + mDatabases.erase(pos); + mTPBs.erase(mTPBs.begin()+index); + delete tpb; + } + + // Signals the Database object that it has been detached from the Transaction + dbi->DetachTransactionImpl(this); +} + +TransactionImpl::TransactionImpl(DatabaseImpl* db, + IBPP::TAM am, IBPP::TIL il, IBPP::TLR lr, IBPP::TFF flags) + : mRefCount(0) +{ + Init(); + AttachDatabaseImpl(db, am, il, lr, flags); +} + +TransactionImpl::~TransactionImpl() +{ + // Rollback the transaction if it was Started + try { if (Started()) Rollback(); } + catch (...) { } + + // Let's detach cleanly all Blobs from this Transaction. + // No Blob object can still maintain pointers to this + // Transaction which is disappearing. + // + // We use a reverse traversal of the array to avoid loops. + // The array shrinks on each loop (mBbCount decreases). + // And during the deletion, there is a packing of the array through a + // copy of elements from the end to the beginning of the array. + try { + while (mBlobs.size() > 0) + mBlobs.back()->DetachTransactionImpl(); + } catch (...) { } + + // Let's detach cleanly all Arrays from this Transaction. + // No Array object can still maintain pointers to this + // Transaction which is disappearing. + try { + while (mArrays.size() > 0) + mArrays.back()->DetachTransactionImpl(); + } catch (...) { } + + // Let's detach cleanly all Statements from this Transaction. + // No Statement object can still maintain pointers to this + // Transaction which is disappearing. + try { + while (mStatements.size() > 0) + mStatements.back()->DetachTransactionImpl(); + } catch (...) { } + + // Very important : let's detach cleanly all Databases from this + // Transaction. No Database object can still maintain pointers to this + // Transaction which is disappearing. + try { + while (mDatabases.size() > 0) + { + size_t i = mDatabases.size()-1; + DetachDatabaseImpl(mDatabases[i]); // <-- remove link to database from mTPBs + // array and destroy TPB object + // Fixed : Maxim Abrashkin on 12 Jun 2002 + //mDatabases.back()->DetachTransaction(this); + } + } catch (...) { } +} + +// +// EOF +// diff --git a/libs/ibpp/user.cpp b/libs/ibpp/user.cpp new file mode 100644 index 00000000..e9cc1b48 --- /dev/null +++ b/libs/ibpp/user.cpp @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File : $Id: user.cpp,v 1.1 2007/05/05 17:00:43 faust Exp $ +// Subject : IBPP, User class implementation +// +/////////////////////////////////////////////////////////////////////////////// +// +// (C) Copyright 2000-2006 T.I.P. Group S.A. and the IBPP Team (www.ibpp.org) +// +// The contents of this file are subject to the IBPP License (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at http://www.ibpp.org or in the 'license.txt' +// file which must have been distributed along with this file. +// +// This software, distributed under the License, is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the +// License for the specific language governing rights and limitations +// under the License. +// +/////////////////////////////////////////////////////////////////////////////// +// +// COMMENTS +// * Tabulations should be set every four characters when editing this file. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _MSC_VER +#pragma warning(disable: 4786 4996) +#ifndef _DEBUG +#pragma warning(disable: 4702) +#endif +#endif + +#include "_ibpp.h" + +#ifdef HAS_HDRSTOP +#pragma hdrstop +#endif + +#include +#include +#include + +using namespace ibpp_internals; + +// Private implementation + +void IBPP::User::copyfrom(const IBPP::User& r) +{ + username = r.username; + password = r.password; + firstname = r.firstname; + middlename = r.middlename; + lastname = r.lastname; + userid = r.userid; + groupid = r.groupid; +} + +// Public implementation + +void IBPP::User::clear() +{ + username.erase(); password.erase(); + firstname.erase(); middlename.erase(); lastname.erase(); + userid = groupid = 0; +} + +// +// EOF +// diff --git a/libs/json/CMakeLists.txt b/libs/json/CMakeLists.txt new file mode 100644 index 00000000..c6031550 --- /dev/null +++ b/libs/json/CMakeLists.txt @@ -0,0 +1,7 @@ +set ( CPP_FILES generator.cpp parser.cpp ) + +add_library ( json STATIC ${CPP_FILES} ) + +target_include_directories ( json PUBLIC include ) + +target_link_libraries ( json common ) diff --git a/libs/json/Makefile b/libs/json/Makefile new file mode 100644 index 00000000..947fce40 --- /dev/null +++ b/libs/json/Makefile @@ -0,0 +1,18 @@ +############################################################################### +# $Id: Makefile,v 1.9 2010/08/18 07:47:03 faust Exp $ +############################################################################### + +LIB_NAME = stgjson + +STGLIBS = -lstgcommon +LIBS = + +SRCS = parser.cpp \ + generator.cpp + +INCS = json_parser.h \ + json_generator.h + +LIB_INCS = -I ../common.lib/include + +include ../Makefile.in diff --git a/libs/json/generator.cpp b/libs/json/generator.cpp new file mode 100644 index 00000000..d18ef04a --- /dev/null +++ b/libs/json/generator.cpp @@ -0,0 +1,82 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/json_generator.h" + +#include + +using STG::JSON::NullGen; +using STG::JSON::BoolGen; +using STG::JSON::StringGen; +using STG::JSON::NumberGen; +using STG::JSON::MapGen; +using STG::JSON::ArrayGen; +using STG::JSON::Callback; + +namespace +{ + +void genString(yajl_gen_t* handle, const std::string& value) +{ + yajl_gen_string(handle, reinterpret_cast(value.c_str()), value.length()); +} + +} + +void NullGen::run(yajl_gen_t* handle) const { yajl_gen_null(handle); } +void BoolGen::run(yajl_gen_t* handle) const { yajl_gen_bool(handle, m_value); } +void StringGen::run(yajl_gen_t* handle) const { genString(handle, m_value); } +void NumberGen::run(yajl_gen_t* handle) const { yajl_gen_number(handle, m_value.c_str(), m_value.length()); } + +void MapGen::run(yajl_gen_t* handle) const +{ + yajl_gen_map_open(handle); + for (Value::const_iterator it = m_value.begin(); it != m_value.end(); ++it) + { + genString(handle, it->first); + it->second.first->run(handle); + } + yajl_gen_map_close(handle); +} + +void ArrayGen::run(yajl_gen_t* handle) const +{ + yajl_gen_array_open(handle); + for (Value::const_iterator it = m_value.begin(); it != m_value.end(); ++it) + it->first->run(handle); + yajl_gen_array_close(handle); +} + +bool STG::JSON::generate(Gen& gen, Callback callback, void* data) +{ + yajl_gen handle = yajl_gen_alloc(NULL); + + gen.run(handle); + + const unsigned char* buf = NULL; + size_t size = 0; + yajl_gen_get_buf(handle, &buf, &size); + + bool res = callback(data, reinterpret_cast(buf), size); + + yajl_gen_free(handle); + + return res; +} diff --git a/libs/json/include/stg/json_generator.h b/libs/json/include/stg/json_generator.h new file mode 100644 index 00000000..4f1523fc --- /dev/null +++ b/libs/json/include/stg/json_generator.h @@ -0,0 +1,122 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_JSON_GENERATOR_H__ +#define __STG_STGLIBS_JSON_GENERATOR_H__ + +#include +#include +#include +#include + +#include + +struct yajl_gen_t; + +namespace STG +{ +namespace JSON +{ + +struct Gen +{ + virtual ~Gen() {} + virtual void run(yajl_gen_t* handle) const = 0; +}; + +struct NullGen : public Gen +{ + virtual void run(yajl_gen_t* handle) const; +}; + +class BoolGen : public Gen +{ + public: + explicit BoolGen(bool value) : m_value(value) {} + virtual void run(yajl_gen_t* handle) const; + private: + bool m_value; +}; + +class StringGen : public Gen +{ + public: + explicit StringGen(const std::string& value) : m_value(value) {} + virtual void run(yajl_gen_t* handle) const; + private: + std::string m_value; +}; + +class NumberGen : public Gen +{ + public: + explicit NumberGen(const std::string& value) : m_value(value) {} + template + explicit NumberGen(const T& value) : m_value(x2str(value)) {} + virtual void run(yajl_gen_t* handle) const; + private: + std::string m_value; +}; + +class MapGen : public Gen +{ + public: + MapGen() {} + virtual ~MapGen() + { + for (Value::iterator it = m_value.begin(); it != m_value.end(); ++it) + if (it->second.second) + delete it->second.first; + } + MapGen& add(const std::string& key, Gen* value) { m_value[key] = std::make_pair(value, true); return *this; } + MapGen& add(const std::string& key, Gen& value) { m_value[key] = std::make_pair(&value, false); return *this; } + virtual void run(yajl_gen_t* handle) const; + private: + typedef std::pair SmartGen; + typedef std::map Value; + Value m_value; +}; + +class ArrayGen : public Gen +{ + public: + ArrayGen() {} + virtual ~ArrayGen() + { + for (Value::iterator it = m_value.begin(); it != m_value.end(); ++it) + if (it->second) + delete it->first; + } + void add(Gen* value) { m_value.push_back(std::make_pair(value, true)); } + void add(Gen& value) { m_value.push_back(std::make_pair(&value, false)); } + virtual void run(yajl_gen_t* handle) const; + private: + typedef std::pair SmartGen; + typedef std::vector Value; + Value m_value; +}; + +typedef bool (*Callback)(void* /*data*/, const char* /*buf*/, size_t /*size*/); +bool generate(Gen& gen, Callback callback, void* data); + +} +} + +#endif diff --git a/libs/json/include/stg/json_parser.h b/libs/json/include/stg/json_parser.h new file mode 100644 index 00000000..a6142579 --- /dev/null +++ b/libs/json/include/stg/json_parser.h @@ -0,0 +1,107 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_JSON_PARSER_H__ +#define __STG_STGLIBS_JSON_PARSER_H__ + +#include "stg/common.h" + +#include +#include + +#include + +namespace STG +{ +namespace JSON +{ + +struct NodeParser +{ + virtual ~NodeParser() {} + + virtual NodeParser* parseNull() { return this; } + virtual NodeParser* parseBoolean(const bool& /*value*/) { return this; } + virtual NodeParser* parseNumber(const std::string& /*value*/) { return this; } + virtual NodeParser* parseString(const std::string& /*value*/) { return this; } + virtual NodeParser* parseStartMap() { return this; } + virtual NodeParser* parseMapKey(const std::string& /*value*/) { return this; } + virtual NodeParser* parseEndMap() { return this; } + virtual NodeParser* parseStartArray() { return this; } + virtual NodeParser* parseEndArray() { return this; } +}; + +class Parser +{ + public: + explicit Parser(NodeParser* topParser); + virtual ~Parser(); + + bool append(const char* data, size_t size); + bool last(); + + private: + class Impl; + boost::scoped_ptr m_impl; +}; + +template +class EnumParser : public NodeParser +{ + public: + typedef std::map Codes; + EnumParser(NodeParser* next, T& data, std::string& dataStr, const Codes& codes) + : m_next(next), m_data(data), m_dataStr(dataStr), m_codes(codes) {} + virtual NodeParser* parseString(const std::string& value) + { + m_dataStr = value; + const typename Codes::const_iterator it = m_codes.find(ToLower(value)); + if (it != m_codes.end()) + m_data = it->second; + return m_next; + } + private: + NodeParser* m_next; + T& m_data; + std::string& m_dataStr; + const Codes& m_codes; +}; + +class PairsParser : public NodeParser +{ + public: + typedef std::map Pairs; + + PairsParser(NodeParser* next, Pairs& pairs) : m_next(next), m_pairs(pairs) {} + + virtual NodeParser* parseStartMap() { return this; } + virtual NodeParser* parseString(const std::string& value) { m_pairs[m_key] = value; return this; } + virtual NodeParser* parseMapKey(const std::string& value) { m_key = value; return this; } + virtual NodeParser* parseEndMap() { return m_next; } + private: + NodeParser* m_next; + Pairs& m_pairs; + std::string m_key; +}; + +} +} + +#endif diff --git a/libs/json/parser.cpp b/libs/json/parser.cpp new file mode 100644 index 00000000..57115048 --- /dev/null +++ b/libs/json/parser.cpp @@ -0,0 +1,123 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "stg/json_parser.h" + +#include + +using STG::JSON::Parser; +using STG::JSON::NodeParser; + +class Parser::Impl +{ + public: + Impl(NodeParser* topParser); + ~Impl() + { + yajl_free(m_handle); + } + + bool append(const char* data, size_t size) { return yajl_parse(m_handle, reinterpret_cast(data), size) == yajl_status_ok; } + bool last() { return yajl_complete_parse(m_handle) == yajl_status_ok; } + + static int parseNull(void* ctx) + { return runParser(ctx, &NodeParser::parseNull); } + static int parseBoolean(void* ctx, int value) + { return runParser(ctx, &NodeParser::parseBoolean, value != 0); } + static int parseNumber(void* ctx, const char* value, size_t size) + { return runParser(ctx, &NodeParser::parseNumber, std::string(value, size)); } + static int parseString(void* ctx, const unsigned char* value, size_t size) + { return runParser(ctx, &NodeParser::parseString, std::string(reinterpret_cast(value), size)); } + static int parseStartMap(void* ctx) + { return runParser(ctx, &NodeParser::parseStartMap); } + static int parseMapKey(void* ctx, const unsigned char* value, size_t size) + { return runParser(ctx, &NodeParser::parseMapKey, std::string(reinterpret_cast(value), size)); } + static int parseEndMap(void* ctx) + { return runParser(ctx, &NodeParser::parseEndMap); } + static int parseStartArray(void* ctx) + { return runParser(ctx, &NodeParser::parseStartArray); } + static int parseEndArray(void* ctx) + { return runParser(ctx, &NodeParser::parseEndArray); } + + private: + yajl_handle m_handle; + NodeParser* m_parser; + + static yajl_callbacks callbacks; + + static NodeParser& getParser(void* ctx) { return *static_cast(ctx)->m_parser; } + static bool runParser(void* ctx, NodeParser* (NodeParser::*func)()) + { + Impl& p = *static_cast(ctx); + NodeParser* next = (p.m_parser->*func)(); + if (next != NULL) + p.m_parser = next; + return next != NULL; + } + template + static bool runParser(void* ctx, NodeParser* (NodeParser::*func)(const T&), const T& value) + { + Impl& p = *static_cast(ctx); + NodeParser* next = (p.m_parser->*func)(value); + if (next != NULL) + p.m_parser = next; + return next != NULL; + } +}; + +yajl_callbacks Parser::Impl::callbacks = { + Parser::Impl::parseNull, + Parser::Impl::parseBoolean, + NULL, // parsing of integer is done using parseNumber + NULL, // parsing of double is done using parseNumber + Parser::Impl::parseNumber, + Parser::Impl::parseString, + Parser::Impl::parseStartMap, + Parser::Impl::parseMapKey, + Parser::Impl::parseEndMap, + Parser::Impl::parseStartArray, + Parser::Impl::parseEndArray +}; + +Parser::Impl::Impl(NodeParser* topParser) + : m_handle(yajl_alloc(&callbacks, NULL, this)), + m_parser(topParser) +{ + yajl_config(m_handle, yajl_allow_multiple_values, 1); +} + +Parser::Parser(NodeParser* topParser) + : m_impl(new Impl(topParser)) +{ +} + +Parser::~Parser() +{ +} + +bool Parser::append(const char* data, size_t size) +{ + return m_impl->append(data, size); +} + +bool Parser::last() +{ + return m_impl->last(); +} diff --git a/libs/logger/CMakeLists.txt b/libs/logger/CMakeLists.txt new file mode 100644 index 00000000..44b1e0d9 --- /dev/null +++ b/libs/logger/CMakeLists.txt @@ -0,0 +1,5 @@ +set ( CPP_FILES logger.cpp ) + +add_library ( logger STATIC ${CPP_FILES} ) + +target_include_directories ( logger PUBLIC include ) diff --git a/libs/logger/Makefile b/libs/logger/Makefile new file mode 100644 index 00000000..f2dbf0c4 --- /dev/null +++ b/libs/logger/Makefile @@ -0,0 +1,11 @@ +############################################################################### +# $Id: Makefile,v 1.3 2007/05/08 14:29:21 faust Exp $ +############################################################################### + +LIB_NAME = stglogger + +SRCS = logger.cpp + +INCS = logger.h + +include ../Makefile.in diff --git a/libs/logger/include/stg/logger.h b/libs/logger/include/stg/logger.h new file mode 100644 index 00000000..60514f4a --- /dev/null +++ b/libs/logger/include/stg/logger.h @@ -0,0 +1,66 @@ +#ifndef STG_LOGGER_H +#define STG_LOGGER_H + +#include + +#include + +class STG_LOGGER; +STG_LOGGER & GetStgLogger(); +//----------------------------------------------------------------------------- +class STG_LOGGER_LOCKER +{ +public: + explicit STG_LOGGER_LOCKER(pthread_mutex_t * m) : mutex(m) { pthread_mutex_lock(mutex); } + ~STG_LOGGER_LOCKER() { pthread_mutex_unlock(mutex); } + +private: + STG_LOGGER_LOCKER(const STG_LOGGER_LOCKER & rvalue); + STG_LOGGER_LOCKER & operator=(const STG_LOGGER_LOCKER & rvalue); + + pthread_mutex_t * mutex; +}; +//----------------------------------------------------------------------------- +class STG_LOGGER +{ +friend STG_LOGGER & GetStgLogger(); +friend class PLUGIN_LOGGER; + +public: + ~STG_LOGGER(); + void SetLogFileName(const std::string & fn); + void operator()(const char * fmt, ...) const; + void operator()(const std::string & line) const { LogString(line.c_str()); } + +private: + STG_LOGGER(); + STG_LOGGER(const STG_LOGGER & rvalue); + STG_LOGGER & operator=(const STG_LOGGER & rvalue); + + const char * LogDate(time_t t) const; + void LogString(const char * str) const; + + std::string fileName; + mutable pthread_mutex_t mutex; +}; +//----------------------------------------------------------------------------- +class PLUGIN_LOGGER +{ +friend PLUGIN_LOGGER GetPluginLogger(const STG_LOGGER& logger, const std::string& pluginName); + +public: + PLUGIN_LOGGER(const PLUGIN_LOGGER& rhs) : m_parent(rhs.m_parent), m_pluginName(rhs.m_pluginName) {} // Need move here. + void operator()(const char* fmt, ...) const; + void operator()(const std::string& line) const; + +private: + PLUGIN_LOGGER& operator=(const PLUGIN_LOGGER&); // Copy assignment is prohibited. + + PLUGIN_LOGGER(const STG_LOGGER & logger, const std::string & pn); + const STG_LOGGER& m_parent; + std::string m_pluginName; +}; + +PLUGIN_LOGGER GetPluginLogger(const STG_LOGGER & logger, const std::string & pluginName); + +#endif //STG_LOGGER_H diff --git a/libs/logger/logger.cpp b/libs/logger/logger.cpp new file mode 100644 index 00000000..20aa133a --- /dev/null +++ b/libs/logger/logger.cpp @@ -0,0 +1,127 @@ +#include "stg/logger.h" + +#include +#include +#include + +#ifdef STG_TIME +extern const volatile time_t stgTime; +#endif +//----------------------------------------------------------------------------- +STG_LOGGER & GetStgLogger() +{ +static STG_LOGGER logger; +return logger; +} +//----------------------------------------------------------------------------- +STG_LOGGER::STG_LOGGER() + : fileName(), + mutex() +{ +pthread_mutex_init(&mutex, NULL); +} +//----------------------------------------------------------------------------- +STG_LOGGER::~STG_LOGGER() +{ +pthread_mutex_destroy(&mutex); +} +//----------------------------------------------------------------------------- +void STG_LOGGER::SetLogFileName(const std::string & fn) +{ +STG_LOGGER_LOCKER lock(&mutex); +fileName = fn; +} +//----------------------------------------------------------------------------- +void STG_LOGGER::operator()(const char * fmt, ...) const +{ +STG_LOGGER_LOCKER lock(&mutex); + +char buff[2048]; + +va_list vl; +va_start(vl, fmt); +vsnprintf(buff, sizeof(buff), fmt, vl); +va_end(vl); + +LogString(buff); +} +//----------------------------------------------------------------------------- +const char * STG_LOGGER::LogDate(time_t t) const +{ +static char s[32]; +if (t == 0) + t = time(NULL); + +struct tm * tt = localtime(&t); + +snprintf(s, 32, "%d-%s%d-%s%d %s%d:%s%d:%s%d", + tt->tm_year + 1900, + tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1, + tt->tm_mday < 10 ? "0" : "", tt->tm_mday, + tt->tm_hour < 10 ? "0" : "", tt->tm_hour, + tt->tm_min < 10 ? "0" : "", tt->tm_min, + tt->tm_sec < 10 ? "0" : "", tt->tm_sec); + +return s; +} +//----------------------------------------------------------------------------- +void STG_LOGGER::LogString(const char * str) const +{ +if (!fileName.empty()) + { + FILE * f = fopen(fileName.c_str(), "at"); + if (f) + { + #ifdef STG_TIME + fprintf(f, "%s", LogDate(stgTime)); + #else + fprintf(f, "%s", LogDate(time(NULL))); + #endif + fprintf(f, " -- "); + fprintf(f, "%s", str); + fprintf(f, "\n"); + fclose(f); + } + else + { + openlog("stg", LOG_NDELAY, LOG_USER); + syslog(LOG_CRIT, "%s", str); + closelog(); + } + } +else + { + openlog("stg", LOG_NDELAY, LOG_USER); + syslog(LOG_CRIT, "%s", str); + closelog(); + } +} +//----------------------------------------------------------------------------- +PLUGIN_LOGGER::PLUGIN_LOGGER(const STG_LOGGER& logger, const std::string& pn) + : m_parent(logger), + m_pluginName(pn) +{ +} +//----------------------------------------------------------------------------- +void PLUGIN_LOGGER::operator()(const char * fmt, ...) const +{ +char buff[2029]; + +va_list vl; +va_start(vl, fmt); +vsnprintf(buff, sizeof(buff), fmt, vl); +va_end(vl); + +m_parent("[%s] %s", m_pluginName.c_str(), buff); +} +//----------------------------------------------------------------------------- +void PLUGIN_LOGGER::operator()(const std::string & line) const +{ +m_parent("[%s] %s", m_pluginName.c_str(), line.c_str()); +} +//----------------------------------------------------------------------------- +PLUGIN_LOGGER GetPluginLogger(const STG_LOGGER & logger, const std::string & pluginName) +{ +return PLUGIN_LOGGER(logger, pluginName); +} +//----------------------------------------------------------------------------- diff --git a/libs/pinger/CMakeLists.txt b/libs/pinger/CMakeLists.txt new file mode 100644 index 00000000..f70e580a --- /dev/null +++ b/libs/pinger/CMakeLists.txt @@ -0,0 +1,7 @@ +set ( CPP_FILES pinger.cpp ) + +add_library ( pinger STATIC ${CPP_FILES} ) + +target_include_directories ( pinger PUBLIC include ) + +target_link_libraries ( pinger common ) diff --git a/libs/pinger/Makefile b/libs/pinger/Makefile new file mode 100644 index 00000000..803f7ac4 --- /dev/null +++ b/libs/pinger/Makefile @@ -0,0 +1,19 @@ +############################################################################### +# $Id: Makefile,v 1.5 2008/12/04 17:13:14 faust Exp $ +############################################################################### + +LIB_NAME = stgpinger + +SRCS = pinger.cpp + +INCS = pinger.h + +LIBS = $(LIB_THREAD) + +LIB_INCS = -I ../common.lib/include + +include ../Makefile.in + +test: all + g++ -c test.cpp + g++ -o test test.o ./libstgpinger.a -lpthread diff --git a/libs/pinger/include/stg/pinger.h b/libs/pinger/include/stg/pinger.h new file mode 100644 index 00000000..26f5f4b3 --- /dev/null +++ b/libs/pinger/include/stg/pinger.h @@ -0,0 +1,135 @@ + /* + $Revision: 1.8 $ + $Date: 2008/05/10 11:59:53 $ + $Author: nobunaga $ + */ + +#ifndef PINGER_H +#define PINGER_H + +#include +#include +#include +#include + +#ifdef LINUX +#include +#include +#include +#endif + +#if defined (FREE_BSD) || defined(DARWIN) +#include +#include +#include +#include +#include +#include +#endif + +#include + +//----------------------------------------------------------------------------- +struct ICMP_HDR +{ +uint8_t type; +uint8_t code; +uint16_t checksum; +union + { + struct + { + uint16_t id; + uint16_t sequence; + } echo; + uint32_t gateway; + struct + { + uint16_t unused; + uint16_t mtu; + } frag; + } un; +}; +//----------------------------------------------------------------------------- +struct IP_HDR +{ + uint8_t ihl:4, + version:4; + uint8_t tos; + uint16_t tot_len; + uint16_t id; + uint16_t frag_off; + uint8_t ttl; + uint8_t protocol; + uint16_t check; + uint32_t saddr; + uint32_t daddr; +}; +//----------------------------------------------------------------------------- +struct PING_IP_TIME +{ +uint32_t ip; +time_t pingTime; +}; +//----------------------------------------------------------------------------- + +#define PING_DATA_LEN (64) +//----------------------------------------------------------------------------- +struct PING_MESSAGE +{ + ICMP_HDR hdr; + char msg[PING_DATA_LEN]; +}; +//----------------------------------------------------------------------------- +class STG_PINGER +{ +public: + typedef std::multimap PingIPs; + typedef PingIPs::size_type SizeType; + + explicit STG_PINGER(time_t delay = 15); + ~STG_PINGER(); + + int Start(); + int Stop(); + void AddIP(uint32_t ip); + void DelIP(uint32_t ip); + SizeType GetPingIPNum() const { return pingIP.size(); } + void PrintAllIP(); + int GetIPTime(uint32_t ip, time_t * t) const; + void SetDelayTime(time_t d) { delay = d; } + time_t GetDelayTime() const { return delay; } + const std::string & GetStrError() const { return errorStr; } + +private: + uint16_t PingCheckSum(void * data, int len); + int SendPing(uint32_t ip); + uint32_t RecvPing(); + void RealAddIP(); + void RealDelIP(); + + static void * RunSendPing(void * d); + static void * RunRecvPing(void * d); + + time_t delay; + bool nonstop; + bool isRunningRecver; + bool isRunningSender; + int sendSocket; + int recvSocket; + pthread_t sendThread; + pthread_t recvThread; + + PING_MESSAGE pmSend; + uint32_t pid; + + std::string errorStr; + + std::multimap pingIP; + std::list ipToAdd; + std::list ipToDel; + + mutable pthread_mutex_t mutex; +}; +//----------------------------------------------------------------------------- +#endif diff --git a/libs/pinger/pinger.cpp b/libs/pinger/pinger.cpp new file mode 100644 index 00000000..1689e294 --- /dev/null +++ b/libs/pinger/pinger.cpp @@ -0,0 +1,346 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "stg/common.h" +#include "stg/locker.h" + +#include "stg/pinger.h" + +#ifdef STG_TIME +extern volatile time_t stgTime; +#endif + +//----------------------------------------------------------------------------- +STG_PINGER::STG_PINGER(time_t d) + : delay(d), + nonstop(false), + isRunningRecver(false), + isRunningSender(false), + sendSocket(-1), + recvSocket(-1), + sendThread(), + recvThread(), + pmSend(), + pid(0), + errorStr(), + pingIP(), + ipToAdd(), + ipToDel(), + mutex() +{ +pthread_mutex_init(&mutex, NULL); +memset(&pmSend, 0, sizeof(pmSend)); +} +//----------------------------------------------------------------------------- +STG_PINGER::~STG_PINGER() +{ +pthread_mutex_destroy(&mutex); +} +//----------------------------------------------------------------------------- +int STG_PINGER::Start() +{ +struct protoent *proto = NULL; +proto = getprotobyname("ICMP"); +sendSocket = socket(PF_INET, SOCK_RAW, proto->p_proto); +recvSocket = socket(PF_INET, SOCK_RAW, proto->p_proto); +nonstop = true; +pid = (int) getpid() % 65535; +if (sendSocket < 0 || recvSocket < 0) + { + errorStr = "Cannot create socket."; + return -1; + } + +if (pthread_create(&sendThread, NULL, RunSendPing, this)) + { + errorStr = "Cannot create send thread."; + return -1; + } + +if (pthread_create(&recvThread, NULL, RunRecvPing, this)) + { + errorStr = "Cannot create recv thread."; + return -1; + } + +return 0; +} +//----------------------------------------------------------------------------- +int STG_PINGER::Stop() +{ +close(recvSocket); +nonstop = false; +if (isRunningRecver) + { + //5 seconds to thread stops itself + for (size_t i = 0; i < 25; i++) + { + if (i % 5 == 0) + SendPing(0x0100007f);//127.0.0.1 + + if (!isRunningRecver) + break; + + struct timespec ts = {0, 200000000}; + nanosleep(&ts, NULL); + } + } + +if (isRunningSender) + { + //5 seconds to thread stops itself + for (size_t i = 0; i < 25; i++) + { + if (!isRunningSender) + break; + + struct timespec ts = {0, 200000000}; + nanosleep(&ts, NULL); + } + } + +close(sendSocket); + +if (isRunningSender || isRunningRecver) + return -1; + +return 0; +} +//----------------------------------------------------------------------------- +void STG_PINGER::AddIP(uint32_t ip) +{ +STG_LOCKER lock(&mutex); +ipToAdd.push_back(ip); +} +//----------------------------------------------------------------------------- +void STG_PINGER::DelIP(uint32_t ip) +{ +STG_LOCKER lock(&mutex); +ipToDel.push_back(ip); +} +//----------------------------------------------------------------------------- +void STG_PINGER::RealAddIP() +{ +STG_LOCKER lock(&mutex); + +std::list::iterator iter; +iter = ipToAdd.begin(); +while (iter != ipToAdd.end()) + { + pingIP.insert(std::make_pair(*iter, 0)); + ++iter; + } +ipToAdd.erase(ipToAdd.begin(), ipToAdd.end()); +} +//----------------------------------------------------------------------------- +void STG_PINGER::RealDelIP() +{ +STG_LOCKER lock(&mutex); + +std::list::iterator iter; +std::multimap::iterator treeIter; +iter = ipToDel.begin(); +while (iter != ipToDel.end()) + { + treeIter = pingIP.find(*iter); + if (treeIter != pingIP.end()) + pingIP.erase(treeIter); + + ++iter; + } +ipToDel.erase(ipToDel.begin(), ipToDel.end()); +} +//----------------------------------------------------------------------------- +void STG_PINGER::PrintAllIP() +{ +STG_LOCKER lock(&mutex); +std::multimap::iterator iter; +iter = pingIP.begin(); +while (iter != pingIP.end()) + { + uint32_t ip = iter->first; + time_t t = iter->second; + std::string s; + x2str(t, s); + printf("ip = %s, time = %9s\n", inet_ntostring(ip).c_str(), s.c_str()); + ++iter; + } + +} +//----------------------------------------------------------------------------- +int STG_PINGER::GetIPTime(uint32_t ip, time_t * t) const +{ +STG_LOCKER lock(&mutex); +std::multimap::const_iterator treeIter; + +treeIter = pingIP.find(ip); +if (treeIter == pingIP.end()) + return -1; + +*t = treeIter->second; +return 0; +} +//----------------------------------------------------------------------------- +uint16_t STG_PINGER::PingCheckSum(void * data, int len) +{ +uint16_t * buf = static_cast(data); +uint32_t sum = 0; +uint32_t result; + +for ( sum = 0; len > 1; len -= 2 ) + sum += *buf++; + +if ( len == 1 ) + sum += *reinterpret_cast(buf); + +sum = (sum >> 16) + (sum & 0xFFFF); +sum += (sum >> 16); +result = ~sum; +return static_cast(result); +} +//----------------------------------------------------------------------------- +int STG_PINGER::SendPing(uint32_t ip) +{ +struct sockaddr_in addr; +memset(&addr, 0, sizeof(addr)); +addr.sin_family = AF_INET; +addr.sin_port = 0; +addr.sin_addr.s_addr = ip; + +memset(&pmSend, 0, sizeof(pmSend)); +pmSend.hdr.type = ICMP_ECHO; +pmSend.hdr.un.echo.id = static_cast(pid); +memcpy(pmSend.msg, &ip, sizeof(ip)); + +pmSend.hdr.checksum = PingCheckSum(&pmSend, sizeof(pmSend)); + +if (sendto(sendSocket, &pmSend, sizeof(pmSend), 0, (sockaddr *)&addr, sizeof(addr)) <= 0 ) + { + errorStr = "Send ping error: " + std::string(strerror(errno)); + return -1; + } + + +return 0; +} +//----------------------------------------------------------------------------- +uint32_t STG_PINGER::RecvPing() +{ +struct sockaddr_in addr; +uint32_t ipAddr = 0; + +char buf[128]; +memset(buf, 0, sizeof(buf)); +socklen_t len = sizeof(addr); + +if (recvfrom(recvSocket, &buf, sizeof(buf), 0, reinterpret_cast(&addr), &len)) + { + struct IP_HDR * ip = static_cast(static_cast(buf)); + struct ICMP_HDR *icmp = static_cast(static_cast(buf + ip->ihl * 4)); + + if (icmp->un.echo.id != pid) + return 0; + + ipAddr = *static_cast(static_cast(buf + sizeof(ICMP_HDR) + ip->ihl * 4)); + } + +return ipAddr; +} +//----------------------------------------------------------------------------- +void * STG_PINGER::RunSendPing(void * d) +{ +sigset_t signalSet; +sigfillset(&signalSet); +pthread_sigmask(SIG_BLOCK, &signalSet, NULL); + +STG_PINGER * pinger = static_cast(d); + +pinger->isRunningSender = true; +time_t lastPing = 0; +while (pinger->nonstop) + { + pinger->RealAddIP(); + pinger->RealDelIP(); + + std::multimap::iterator iter; + iter = pinger->pingIP.begin(); + while (iter != pinger->pingIP.end()) + { + pinger->SendPing(iter->first); + ++iter; + } + + time_t currTime; + + #ifdef STG_TIME + lastPing = stgTime; + currTime = stgTime; + #else + currTime = lastPing = time(NULL); + #endif + + while (currTime - lastPing < pinger->delay && pinger->nonstop) + { + #ifdef STG_TIME + currTime = stgTime; + #else + currTime = time(NULL); + #endif + struct timespec ts = {0, 20000000}; + nanosleep(&ts, NULL); + } + } + +pinger->isRunningSender = false; + +return NULL; +} +//----------------------------------------------------------------------------- +void * STG_PINGER::RunRecvPing(void * d) +{ +sigset_t signalSet; +sigfillset(&signalSet); +pthread_sigmask(SIG_BLOCK, &signalSet, NULL); + +STG_PINGER * pinger = static_cast(d); + +pinger->isRunningRecver = true; + +while (pinger->nonstop) + { + uint32_t ip = pinger->RecvPing(); + + if (ip) + { + std::multimap::iterator treeIterUpper = pinger->pingIP.upper_bound(ip); + std::multimap::iterator treeIterLower = pinger->pingIP.lower_bound(ip); + while (treeIterUpper != treeIterLower) + { + #ifdef STG_TIME + treeIterLower->second = stgTime; + #else + treeIterLower->second = time(NULL); + #endif + ++treeIterLower; + } + } + + } +pinger->isRunningRecver = false; +return NULL; +} +//----------------------------------------------------------------------------- diff --git a/libs/scriptexecuter/CMakeLists.txt b/libs/scriptexecuter/CMakeLists.txt new file mode 100644 index 00000000..88d9b23d --- /dev/null +++ b/libs/scriptexecuter/CMakeLists.txt @@ -0,0 +1,5 @@ +set ( C_FILES scriptexecuter.c ) + +add_library ( scriptexecuter STATIC ${C_FILES} ) + +target_include_directories ( scriptexecuter PUBLIC include ) diff --git a/libs/scriptexecuter/Makefile b/libs/scriptexecuter/Makefile new file mode 100644 index 00000000..92538b12 --- /dev/null +++ b/libs/scriptexecuter/Makefile @@ -0,0 +1,11 @@ +############################################################################### +# $Id: Makefile,v 1.6 2010/01/21 13:02:12 faust Exp $ +############################################################################### + +LIB_NAME = stgscriptexecuter + +SRCS = scriptexecuter.c + +INCS = scriptexecuter.h + +include ../Makefile.in diff --git a/libs/scriptexecuter/include/stg/scriptexecuter.h b/libs/scriptexecuter/include/stg/scriptexecuter.h new file mode 100644 index 00000000..947669c7 --- /dev/null +++ b/libs/scriptexecuter/include/stg/scriptexecuter.h @@ -0,0 +1,19 @@ +#ifndef SCRIPT_EXECUTER_H +#define SCRIPT_EXECUTER_H + +#ifdef __cplusplus +extern "C" { +#endif + +int ScriptExec(const char * str); +#if defined(LINUX) || defined(DARWIN) +void Executer(int msgID, pid_t pid, char * procName); +#else +void Executer(int msgID, pid_t pid); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/libs/scriptexecuter/scriptexecuter.c b/libs/scriptexecuter/scriptexecuter.c new file mode 100644 index 00000000..bdf60230 --- /dev/null +++ b/libs/scriptexecuter/scriptexecuter.c @@ -0,0 +1,110 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "stg/scriptexecuter.h" + +#define MAX_SCRIPT_LEN (1100) + +static int msgid; +static int nonstop; + +//----------------------------------------------------------------------------- +struct SCRIPT_DATA +{ + long mtype; + char script[MAX_SCRIPT_LEN]; +} sd; +//----------------------------------------------------------------------------- +static void CatchUSR1Executer() +{ +nonstop = 0; +} +//----------------------------------------------------------------------------- +int ScriptExec(const char * str) +{ +if (strlen(str) >= MAX_SCRIPT_LEN) + return -1; + +strncpy(sd.script, str, MAX_SCRIPT_LEN); +sd.mtype = 1; +if (msgsnd(msgid, (void *)&sd, MAX_SCRIPT_LEN, 0) < 0) + return -1; + +return 0; +} +//----------------------------------------------------------------------------- +#if defined(LINUX) || defined(DARWIN) +void Executer(int msgID, pid_t pid, char * procName) +#else +void Executer(int msgID, pid_t pid) +#endif +{ +struct SCRIPT_DATA sd; +struct sigaction newsa, oldsa; +sigset_t sigmask; + +msgid = msgID; +if (pid) + return; +nonstop = 1; + +#if defined(LINUX) || defined(DARWIN) +memset(procName, 0, strlen(procName)); +strcpy(procName, "stg-exec"); +#else +setproctitle("stg-exec"); +#endif + +sigemptyset(&sigmask); +sigaddset(&sigmask, SIGTERM); +newsa.sa_handler = SIG_IGN; +newsa.sa_mask = sigmask; +newsa.sa_flags = 0; +sigaction(SIGTERM, &newsa, &oldsa); + +sigemptyset(&sigmask); +sigaddset(&sigmask, SIGINT); +newsa.sa_handler = SIG_IGN; +newsa.sa_mask = sigmask; +newsa.sa_flags = 0; +sigaction(SIGINT, &newsa, &oldsa); + +sigemptyset(&sigmask); +sigaddset(&sigmask, SIGHUP); +newsa.sa_handler = SIG_IGN; +newsa.sa_mask = sigmask; +newsa.sa_flags = 0; +sigaction(SIGHUP, &newsa, &oldsa); + +sigemptyset(&sigmask); +sigaddset(&sigmask, SIGUSR1); +newsa.sa_handler = CatchUSR1Executer; +newsa.sa_mask = sigmask; +newsa.sa_flags = 0; +sigaction(SIGUSR1, &newsa, &oldsa); + +while (nonstop) + { + sd.mtype = 1; + int ret = msgrcv(msgid, &sd, MAX_SCRIPT_LEN, 0, 0); + + if (ret < 0) + { + usleep(20000); + continue; + } + ret = system(sd.script); + if (ret == -1) + { + // Fork failed + } + } +} +//----------------------------------------------------------------------------- diff --git a/libs/smux/ANY.c b/libs/smux/ANY.c new file mode 100644 index 00000000..612238b6 --- /dev/null +++ b/libs/smux/ANY.c @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +static asn_OCTET_STRING_specifics_t asn_DEF_ANY_specs = { + sizeof(ANY_t), + offsetof(ANY_t, _asn_ctx), + 2 /* Special indicator that this is an ANY type */ +}; +asn_TYPE_descriptor_t asn_DEF_ANY = { + "ANY", + "ANY", + OCTET_STRING_free, + OCTET_STRING_print, + asn_generic_no_constraint, + OCTET_STRING_decode_ber, + OCTET_STRING_encode_der, + OCTET_STRING_decode_xer_hex, + ANY_encode_xer, + 0, 0, + 0, /* Use generic outmost tag fetcher */ + 0, 0, 0, 0, + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + &asn_DEF_ANY_specs, +}; + + +asn_enc_rval_t +ANY_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + + if(flags & XER_F_CANONICAL) { + /* + * Canonical XER-encoding of ANY type is not supported. + */ + _ASN_ENCODE_FAILED; + } + + /* Dump as binary */ + return OCTET_STRING_encode_xer(td, sptr, ilevel, flags, cb, app_key); +} + +struct _callback_arg { + uint8_t *buffer; + size_t offset; + size_t size; +}; + +static int ANY__consume_bytes(const void *buffer, size_t size, void *key); + +int +ANY_fromType(ANY_t *st, asn_TYPE_descriptor_t *td, void *sptr) { + struct _callback_arg arg; + asn_enc_rval_t erval; + + if(!st || !td) { + errno = EINVAL; + return -1; + } + + if(!sptr) { + if(st->buf) FREEMEM(st->buf); + st->size = 0; + return 0; + } + + arg.offset = arg.size = 0; + arg.buffer = 0; + + erval = der_encode(td, sptr, ANY__consume_bytes, &arg); + if(erval.encoded == -1) { + if(arg.buffer) FREEMEM(arg.buffer); + return -1; + } + assert((size_t)erval.encoded == arg.offset); + + if(st->buf) FREEMEM(st->buf); + st->buf = arg.buffer; + st->size = arg.offset; + + return 0; +} + +ANY_t * +ANY_new_fromType(asn_TYPE_descriptor_t *td, void *sptr) { + ANY_t tmp; + ANY_t *st; + + if(!td || !sptr) { + errno = EINVAL; + return 0; + } + + memset(&tmp, 0, sizeof(tmp)); + + if(ANY_fromType(&tmp, td, sptr)) return 0; + + st = (ANY_t *)CALLOC(1, sizeof(ANY_t)); + if(st) { + *st = tmp; + return st; + } else { + FREEMEM(tmp.buf); + return 0; + } +} + +int +ANY_to_type(ANY_t *st, asn_TYPE_descriptor_t *td, void **struct_ptr) { + asn_dec_rval_t rval; + void *newst = 0; + + if(!st || !td || !struct_ptr) { + errno = EINVAL; + return -1; + } + + if(st->buf == 0) { + /* Nothing to convert, make it empty. */ + *struct_ptr = (void *)0; + return 0; + } + + rval = ber_decode(0, td, (void **)&newst, st->buf, st->size); + if(rval.code == RC_OK) { + *struct_ptr = newst; + return 0; + } else { + /* Remove possibly partially decoded data. */ + ASN_STRUCT_FREE(*td, newst); + return -1; + } +} + +static int ANY__consume_bytes(const void *buffer, size_t size, void *key) { + struct _callback_arg *arg = (struct _callback_arg *)key; + + if((arg->offset + size) >= arg->size) { + size_t nsize = (arg->size ? arg->size << 2 : 16) + size; + void *p = REALLOC(arg->buffer, nsize); + if(!p) return -1; + arg->buffer = (uint8_t *)p; + arg->size = nsize; + } + + memcpy(arg->buffer + arg->offset, buffer, size); + arg->offset += size; + assert(arg->offset < arg->size); + + return 0; +} + diff --git a/libs/smux/ApplicationSyntax.c b/libs/smux/ApplicationSyntax.c new file mode 100644 index 00000000..a4f97e2c --- /dev/null +++ b/libs/smux/ApplicationSyntax.c @@ -0,0 +1,97 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "ApplicationSyntax.h" + +static asn_TYPE_member_t asn_MBR_ApplicationSyntax_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ApplicationSyntax, choice.address), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_NetworkAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "address" + }, + { ATF_NOFLAGS, 0, offsetof(struct ApplicationSyntax, choice.counter), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "counter" + }, + { ATF_NOFLAGS, 0, offsetof(struct ApplicationSyntax, choice.gauge), + (ASN_TAG_CLASS_APPLICATION | (2 << 2)), + 0, + &asn_DEF_Gauge, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "gauge" + }, + { ATF_NOFLAGS, 0, offsetof(struct ApplicationSyntax, choice.ticks), + (ASN_TAG_CLASS_APPLICATION | (3 << 2)), + 0, + &asn_DEF_TimeTicks, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ticks" + }, + { ATF_NOFLAGS, 0, offsetof(struct ApplicationSyntax, choice.arbitrary), + (ASN_TAG_CLASS_APPLICATION | (4 << 2)), + 0, + &asn_DEF_Opaque, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "arbitrary" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_ApplicationSyntax_tag2el_1[] = { + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 0, 0, 0 }, /* internet at 113 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 1, 0, 0 }, /* counter at 91 */ + { (ASN_TAG_CLASS_APPLICATION | (2 << 2)), 2, 0, 0 }, /* gauge at 94 */ + { (ASN_TAG_CLASS_APPLICATION | (3 << 2)), 3, 0, 0 }, /* ticks at 97 */ + { (ASN_TAG_CLASS_APPLICATION | (4 << 2)), 4, 0, 0 } /* arbitrary at 104 */ +}; +static asn_CHOICE_specifics_t asn_SPC_ApplicationSyntax_specs_1 = { + sizeof(struct ApplicationSyntax), + offsetof(struct ApplicationSyntax, _asn_ctx), + offsetof(struct ApplicationSyntax, present), + sizeof(((struct ApplicationSyntax *)0)->present), + asn_MAP_ApplicationSyntax_tag2el_1, + 5, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +asn_TYPE_descriptor_t asn_DEF_ApplicationSyntax = { + "ApplicationSyntax", + "ApplicationSyntax", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + 0, /* No PER visible constraints */ + asn_MBR_ApplicationSyntax_1, + 5, /* Elements count */ + &asn_SPC_ApplicationSyntax_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/AtEntry.c b/libs/smux/AtEntry.c new file mode 100644 index 00000000..bf3b9ba9 --- /dev/null +++ b/libs/smux/AtEntry.c @@ -0,0 +1,81 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "AtEntry.h" + +static asn_TYPE_member_t asn_MBR_AtEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct AtEntry, atIfIndex), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "atIfIndex" + }, + { ATF_NOFLAGS, 0, offsetof(struct AtEntry, atPhysAddress), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_PhysAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "atPhysAddress" + }, + { ATF_NOFLAGS, 0, offsetof(struct AtEntry, atNetAddress), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_NetworkAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "atNetAddress" + }, +}; +static ber_tlv_tag_t asn_DEF_AtEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_AtEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* atIfIndex at 154 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 1, 0, 0 }, /* atPhysAddress at 157 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 2, 0, 0 } /* internet at 113 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_AtEntry_specs_1 = { + sizeof(struct AtEntry), + offsetof(struct AtEntry, _asn_ctx), + asn_MAP_AtEntry_tag2el_1, + 3, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_AtEntry = { + "AtEntry", + "AtEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_AtEntry_tags_1, + sizeof(asn_DEF_AtEntry_tags_1) + /sizeof(asn_DEF_AtEntry_tags_1[0]), /* 1 */ + asn_DEF_AtEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_AtEntry_tags_1) + /sizeof(asn_DEF_AtEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_AtEntry_1, + 3, /* Elements count */ + &asn_SPC_AtEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/BIT_STRING.c b/libs/smux/BIT_STRING.c new file mode 100644 index 00000000..6469d4fd --- /dev/null +++ b/libs/smux/BIT_STRING.c @@ -0,0 +1,188 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * BIT STRING basic type description. + */ +static ber_tlv_tag_t asn_DEF_BIT_STRING_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)) +}; +static asn_OCTET_STRING_specifics_t asn_DEF_BIT_STRING_specs = { + sizeof(BIT_STRING_t), + offsetof(BIT_STRING_t, _asn_ctx), + 1, /* Special indicator that this is a BIT STRING type */ +}; +asn_TYPE_descriptor_t asn_DEF_BIT_STRING = { + "BIT STRING", + "BIT_STRING", + OCTET_STRING_free, /* Implemented in terms of OCTET STRING */ + BIT_STRING_print, + BIT_STRING_constraint, + OCTET_STRING_decode_ber, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_encode_der, /* Implemented in terms of OCTET STRING */ + OCTET_STRING_decode_xer_binary, + BIT_STRING_encode_xer, + OCTET_STRING_decode_uper, /* Unaligned PER decoder */ + OCTET_STRING_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_BIT_STRING_tags, + sizeof(asn_DEF_BIT_STRING_tags) + / sizeof(asn_DEF_BIT_STRING_tags[0]), + asn_DEF_BIT_STRING_tags, /* Same as above */ + sizeof(asn_DEF_BIT_STRING_tags) + / sizeof(asn_DEF_BIT_STRING_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + &asn_DEF_BIT_STRING_specs +}; + +/* + * BIT STRING generic constraint. + */ +int +BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + + if(st && st->buf) { + if(st->size == 1 && st->bits_unused) { + _ASN_CTFAIL(app_key, td, + "%s: invalid padding byte (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + } else { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + return 0; +} + +static char *_bit_pattern[16] = { + "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", + "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" +}; + +asn_enc_rval_t +BIT_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + char scratch[128]; + char *p = scratch; + char *scend = scratch + (sizeof(scratch) - 10); + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + int xcan = (flags & XER_F_CANONICAL); + uint8_t *buf; + uint8_t *end; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + buf = st->buf; + end = buf + st->size - 1; /* Last byte is special */ + + /* + * Binary dump + */ + for(; buf < end; buf++) { + int v = *buf; + int nline = xcan?0:(((buf - st->buf) % 8) == 0); + if(p >= scend || nline) { + er.encoded += p - scratch; + _ASN_CALLBACK(scratch, p - scratch); + p = scratch; + if(nline) _i_ASN_TEXT_INDENT(1, ilevel); + } + memcpy(p + 0, _bit_pattern[v >> 4], 4); + memcpy(p + 4, _bit_pattern[v & 0x0f], 4); + p += 8; + } + + if(!xcan && ((buf - st->buf) % 8) == 0) + _i_ASN_TEXT_INDENT(1, ilevel); + er.encoded += p - scratch; + _ASN_CALLBACK(scratch, p - scratch); + p = scratch; + + if(buf == end) { + int v = *buf; + int ubits = st->bits_unused; + int i; + for(i = 7; i >= ubits; i--) + *p++ = (v & (1 << i)) ? 0x31 : 0x30; + er.encoded += p - scratch; + _ASN_CALLBACK(scratch, p - scratch); + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + + +/* + * BIT STRING specific contents printer. + */ +int +BIT_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + static const char *h2c = "0123456789ABCDEF"; + char scratch[64]; + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + uint8_t *buf; + uint8_t *end; + char *p = scratch; + + (void)td; /* Unused argument */ + + if(!st || !st->buf) + return (cb("", 8, app_key) < 0) ? -1 : 0; + + ilevel++; + buf = st->buf; + end = buf + st->size; + + /* + * Hexadecimal dump. + */ + for(; buf < end; buf++) { + if((buf - st->buf) % 16 == 0 && (st->size > 16) + && buf != st->buf) { + _i_INDENT(1); + /* Dump the string */ + if(cb(scratch, p - scratch, app_key) < 0) return -1; + p = scratch; + } + *p++ = h2c[*buf >> 4]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x20; + } + + if(p > scratch) { + p--; /* Eat the tailing space */ + + if((st->size > 16)) { + _i_INDENT(1); + } + + /* Dump the incomplete 16-bytes row */ + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + } + + return 0; +} + diff --git a/libs/smux/BOOLEAN.c b/libs/smux/BOOLEAN.c new file mode 100644 index 00000000..bb4697c2 --- /dev/null +++ b/libs/smux/BOOLEAN.c @@ -0,0 +1,284 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * BOOLEAN basic type description. + */ +static ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (1 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_BOOLEAN = { + "BOOLEAN", + "BOOLEAN", + BOOLEAN_free, + BOOLEAN_print, + asn_generic_no_constraint, + BOOLEAN_decode_ber, + BOOLEAN_encode_der, + BOOLEAN_decode_xer, + BOOLEAN_encode_xer, + BOOLEAN_decode_uper, /* Unaligned PER decoder */ + BOOLEAN_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_BOOLEAN_tags, + sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]), + asn_DEF_BOOLEAN_tags, /* Same as above */ + sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Decode BOOLEAN type. + */ +asn_dec_rval_t +BOOLEAN_decode_ber(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **bool_value, const void *buf_ptr, size_t size, + int tag_mode) { + BOOLEAN_t *st = (BOOLEAN_t *)*bool_value; + asn_dec_rval_t rval; + ber_tlv_len_t length; + ber_tlv_len_t lidx; + + if(st == NULL) { + st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st))); + if(st == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)", + td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("Boolean length is %d bytes", (int)length); + + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * Compute boolean value. + */ + for(*st = 0, lidx = 0; + (lidx < length) && *st == 0; lidx++) { + /* + * Very simple approach: read bytes until the end or + * value is already TRUE. + * BOOLEAN is not supposed to contain meaningful data anyway. + */ + *st |= ((const uint8_t *)buf_ptr)[lidx]; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d", + (long)rval.consumed, (long)length, + td->name, *st); + + return rval; +} + +asn_enc_rval_t +BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t erval; + BOOLEAN_t *st = (BOOLEAN_t *)sptr; + + erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key); + if(erval.encoded == -1) { + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + + if(cb) { + uint8_t bool_value; + + bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */ + + if(cb(&bool_value, 1, app_key) < 0) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + } + + erval.encoded += 1; + + _ASN_ENCODED_OK(erval); +} + + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +static enum xer_pbd_rval +BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + BOOLEAN_t *st = (BOOLEAN_t *)sptr; + const char *p = (const char *)chunk_buf; + + (void)td; + + if(chunk_size && p[0] == 0x3c /* '<' */) { + switch(xer_check_tag(chunk_buf, chunk_size, "false")) { + case XCT_BOTH: + /* "" */ + *st = 0; + break; + case XCT_UNKNOWN_BO: + if(xer_check_tag(chunk_buf, chunk_size, "true") + != XCT_BOTH) + return XPBD_BROKEN_ENCODING; + /* "" */ + *st = 1; /* Or 0xff as in DER?.. */ + break; + default: + return XPBD_BROKEN_ENCODING; + } + return XPBD_BODY_CONSUMED; + } else { + if(xer_is_whitespace(chunk_buf, chunk_size)) + return XPBD_NOT_BODY_IGNORE; + else + return XPBD_BROKEN_ENCODING; + } +} + + +asn_dec_rval_t +BOOLEAN_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size, + BOOLEAN__xer_body_decode); +} + +asn_enc_rval_t +BOOLEAN_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const BOOLEAN_t *st = (const BOOLEAN_t *)sptr; + asn_enc_rval_t er; + + (void)ilevel; + (void)flags; + + if(!st) _ASN_ENCODE_FAILED; + + if(*st) { + _ASN_CALLBACK("", 7); + er.encoded = 7; + } else { + _ASN_CALLBACK("", 8); + er.encoded = 8; + } + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +int +BOOLEAN_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const BOOLEAN_t *st = (const BOOLEAN_t *)sptr; + const char *buf; + size_t buflen; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(st) { + if(*st) { + buf = "TRUE"; + buflen = 4; + } else { + buf = "FALSE"; + buflen = 5; + } + } else { + buf = ""; + buflen = 8; + } + + return (cb(buf, buflen, app_key) < 0) ? -1 : 0; +} + +void +BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + if(td && ptr && !contents_only) { + FREEMEM(ptr); + } +} + +asn_dec_rval_t +BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + BOOLEAN_t *st = (BOOLEAN_t *)*sptr; + + (void)opt_codec_ctx; + (void)constraints; + + if(!st) { + st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st))); + if(!st) _ASN_DECODE_FAILED; + } + + /* + * Extract a single bit + */ + switch(per_get_few_bits(pd, 1)) { + case 1: *st = 1; break; + case 0: *st = 0; break; + case -1: default: _ASN_DECODE_FAILED; + } + + ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE"); + + rv.code = RC_OK; + rv.consumed = 1; + return rv; +} + + +asn_enc_rval_t +BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + const BOOLEAN_t *st = (const BOOLEAN_t *)sptr; + asn_enc_rval_t er; + + (void)constraints; + + if(!st) _ASN_ENCODE_FAILED; + + per_put_few_bits(po, *st ? 1 : 0, 1); + + _ASN_ENCODED_OK(er); +} diff --git a/libs/smux/CMakeLists.txt b/libs/smux/CMakeLists.txt new file mode 100644 index 00000000..81fe22f4 --- /dev/null +++ b/libs/smux/CMakeLists.txt @@ -0,0 +1,5 @@ +file ( GLOB C_FILES *.c ) + +add_library ( smux STATIC ${C_FILES} ) + +target_include_directories ( smux PUBLIC include include/stg ) diff --git a/libs/smux/ClosePDU.c b/libs/smux/ClosePDU.c new file mode 100644 index 00000000..a97e3b45 --- /dev/null +++ b/libs/smux/ClosePDU.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "ClosePDU.h" + +int +ClosePDU_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_INTEGER.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using INTEGER, + * so here we adjust the DEF accordingly. + */ +static void +ClosePDU_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_INTEGER.free_struct; + td->print_struct = asn_DEF_INTEGER.print_struct; + td->ber_decoder = asn_DEF_INTEGER.ber_decoder; + td->der_encoder = asn_DEF_INTEGER.der_encoder; + td->xer_decoder = asn_DEF_INTEGER.xer_decoder; + td->xer_encoder = asn_DEF_INTEGER.xer_encoder; + td->uper_decoder = asn_DEF_INTEGER.uper_decoder; + td->uper_encoder = asn_DEF_INTEGER.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_INTEGER.per_constraints; + td->elements = asn_DEF_INTEGER.elements; + td->elements_count = asn_DEF_INTEGER.elements_count; + td->specifics = asn_DEF_INTEGER.specifics; +} + +void +ClosePDU_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + ClosePDU_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +ClosePDU_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + ClosePDU_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +ClosePDU_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + ClosePDU_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +ClosePDU_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + ClosePDU_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +ClosePDU_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + ClosePDU_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +ClosePDU_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + ClosePDU_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_ClosePDU_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_ClosePDU = { + "ClosePDU", + "ClosePDU", + ClosePDU_free, + ClosePDU_print, + ClosePDU_constraint, + ClosePDU_decode_ber, + ClosePDU_encode_der, + ClosePDU_decode_xer, + ClosePDU_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ClosePDU_tags_1, + sizeof(asn_DEF_ClosePDU_tags_1) + /sizeof(asn_DEF_ClosePDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_ClosePDU_tags_1, /* Same as above */ + sizeof(asn_DEF_ClosePDU_tags_1) + /sizeof(asn_DEF_ClosePDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* Defined elsewhere */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/Counter.c b/libs/smux/Counter.c new file mode 100644 index 00000000..c2389fdb --- /dev/null +++ b/libs/smux/Counter.c @@ -0,0 +1,134 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "Counter.h" + +int +Counter_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const INTEGER_t *st = (const INTEGER_t *)sptr; + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + if(asn_INTEGER2long(st, &value)) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value too large (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + if((value >= 0 && value <= 4294967295)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +/* + * This type is implemented using INTEGER, + * so here we adjust the DEF accordingly. + */ +static void +Counter_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_INTEGER.free_struct; + td->print_struct = asn_DEF_INTEGER.print_struct; + td->ber_decoder = asn_DEF_INTEGER.ber_decoder; + td->der_encoder = asn_DEF_INTEGER.der_encoder; + td->xer_decoder = asn_DEF_INTEGER.xer_decoder; + td->xer_encoder = asn_DEF_INTEGER.xer_encoder; + td->uper_decoder = asn_DEF_INTEGER.uper_decoder; + td->uper_encoder = asn_DEF_INTEGER.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_INTEGER.per_constraints; + td->elements = asn_DEF_INTEGER.elements; + td->elements_count = asn_DEF_INTEGER.elements_count; + td->specifics = asn_DEF_INTEGER.specifics; +} + +void +Counter_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + Counter_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +Counter_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + Counter_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +Counter_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + Counter_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +Counter_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + Counter_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +Counter_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + Counter_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +Counter_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + Counter_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_Counter_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_Counter = { + "Counter", + "Counter", + Counter_free, + Counter_print, + Counter_constraint, + Counter_decode_ber, + Counter_encode_der, + Counter_decode_xer, + Counter_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_Counter_tags_1, + sizeof(asn_DEF_Counter_tags_1) + /sizeof(asn_DEF_Counter_tags_1[0]) - 1, /* 1 */ + asn_DEF_Counter_tags_1, /* Same as above */ + sizeof(asn_DEF_Counter_tags_1) + /sizeof(asn_DEF_Counter_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/DisplayString.c b/libs/smux/DisplayString.c new file mode 100644 index 00000000..f3c57405 --- /dev/null +++ b/libs/smux/DisplayString.c @@ -0,0 +1,110 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "DisplayString.h" + +int +DisplayString_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_OCTET_STRING.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using OCTET_STRING, + * so here we adjust the DEF accordingly. + */ +static void +DisplayString_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_OCTET_STRING.free_struct; + td->print_struct = asn_DEF_OCTET_STRING.print_struct; + td->ber_decoder = asn_DEF_OCTET_STRING.ber_decoder; + td->der_encoder = asn_DEF_OCTET_STRING.der_encoder; + td->xer_decoder = asn_DEF_OCTET_STRING.xer_decoder; + td->xer_encoder = asn_DEF_OCTET_STRING.xer_encoder; + td->uper_decoder = asn_DEF_OCTET_STRING.uper_decoder; + td->uper_encoder = asn_DEF_OCTET_STRING.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_OCTET_STRING.per_constraints; + td->elements = asn_DEF_OCTET_STRING.elements; + td->elements_count = asn_DEF_OCTET_STRING.elements_count; + td->specifics = asn_DEF_OCTET_STRING.specifics; +} + +void +DisplayString_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + DisplayString_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +DisplayString_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + DisplayString_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +DisplayString_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + DisplayString_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +DisplayString_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + DisplayString_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +DisplayString_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + DisplayString_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +DisplayString_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + DisplayString_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_DisplayString_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_DisplayString = { + "DisplayString", + "DisplayString", + DisplayString_free, + DisplayString_print, + DisplayString_constraint, + DisplayString_decode_ber, + DisplayString_encode_der, + DisplayString_decode_xer, + DisplayString_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_DisplayString_tags_1, + sizeof(asn_DEF_DisplayString_tags_1) + /sizeof(asn_DEF_DisplayString_tags_1[0]), /* 1 */ + asn_DEF_DisplayString_tags_1, /* Same as above */ + sizeof(asn_DEF_DisplayString_tags_1) + /sizeof(asn_DEF_DisplayString_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/EgpNeighEntry.c b/libs/smux/EgpNeighEntry.c new file mode 100644 index 00000000..07c28afa --- /dev/null +++ b/libs/smux/EgpNeighEntry.c @@ -0,0 +1,201 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "EgpNeighEntry.h" + +static asn_TYPE_member_t asn_MBR_EgpNeighEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighState), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighState" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighAddr), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighAddr" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighAs), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighAs" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighInMsgs), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighInMsgs" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighInErrs), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighInErrs" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighOutMsgs), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighOutMsgs" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighOutErrs), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighOutErrs" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighInErrMsgs), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighInErrMsgs" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighOutErrMsgs), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighOutErrMsgs" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighStateUps), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighStateUps" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighStateDowns), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighStateDowns" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighIntervalHello), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighIntervalHello" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighIntervalPoll), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighIntervalPoll" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighMode), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighMode" + }, + { ATF_NOFLAGS, 0, offsetof(struct EgpNeighEntry, egpNeighEventTrigger), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "egpNeighEventTrigger" + }, +}; +static ber_tlv_tag_t asn_DEF_EgpNeighEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_EgpNeighEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 5 }, /* egpNeighState at 267 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, -1, 4 }, /* egpNeighAs at 271 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 11, -2, 3 }, /* egpNeighIntervalHello at 290 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 12, -3, 2 }, /* egpNeighIntervalPoll at 292 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 13, -4, 1 }, /* egpNeighMode at 294 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 14, -5, 0 }, /* egpNeighEventTrigger at 297 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 1, 0, 0 }, /* egpNeighAddr at 269 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 3, 0, 7 }, /* egpNeighInMsgs at 273 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 4, -1, 6 }, /* egpNeighInErrs at 275 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 5, -2, 5 }, /* egpNeighOutMsgs at 277 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 6, -3, 4 }, /* egpNeighOutErrs at 279 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 7, -4, 3 }, /* egpNeighInErrMsgs at 282 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 8, -5, 2 }, /* egpNeighOutErrMsgs at 284 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 9, -6, 1 }, /* egpNeighStateUps at 286 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 10, -7, 0 } /* egpNeighStateDowns at 288 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_EgpNeighEntry_specs_1 = { + sizeof(struct EgpNeighEntry), + offsetof(struct EgpNeighEntry, _asn_ctx), + asn_MAP_EgpNeighEntry_tag2el_1, + 15, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_EgpNeighEntry = { + "EgpNeighEntry", + "EgpNeighEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_EgpNeighEntry_tags_1, + sizeof(asn_DEF_EgpNeighEntry_tags_1) + /sizeof(asn_DEF_EgpNeighEntry_tags_1[0]), /* 1 */ + asn_DEF_EgpNeighEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_EgpNeighEntry_tags_1) + /sizeof(asn_DEF_EgpNeighEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_EgpNeighEntry_1, + 15, /* Elements count */ + &asn_SPC_EgpNeighEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/Gauge.c b/libs/smux/Gauge.c new file mode 100644 index 00000000..190b91f4 --- /dev/null +++ b/libs/smux/Gauge.c @@ -0,0 +1,134 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "Gauge.h" + +int +Gauge_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const INTEGER_t *st = (const INTEGER_t *)sptr; + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + if(asn_INTEGER2long(st, &value)) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value too large (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + if((value >= 0 && value <= 4294967295)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +/* + * This type is implemented using INTEGER, + * so here we adjust the DEF accordingly. + */ +static void +Gauge_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_INTEGER.free_struct; + td->print_struct = asn_DEF_INTEGER.print_struct; + td->ber_decoder = asn_DEF_INTEGER.ber_decoder; + td->der_encoder = asn_DEF_INTEGER.der_encoder; + td->xer_decoder = asn_DEF_INTEGER.xer_decoder; + td->xer_encoder = asn_DEF_INTEGER.xer_encoder; + td->uper_decoder = asn_DEF_INTEGER.uper_decoder; + td->uper_encoder = asn_DEF_INTEGER.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_INTEGER.per_constraints; + td->elements = asn_DEF_INTEGER.elements; + td->elements_count = asn_DEF_INTEGER.elements_count; + td->specifics = asn_DEF_INTEGER.specifics; +} + +void +Gauge_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + Gauge_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +Gauge_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + Gauge_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +Gauge_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + Gauge_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +Gauge_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + Gauge_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +Gauge_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + Gauge_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +Gauge_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + Gauge_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_Gauge_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (2 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_Gauge = { + "Gauge", + "Gauge", + Gauge_free, + Gauge_print, + Gauge_constraint, + Gauge_decode_ber, + Gauge_encode_der, + Gauge_decode_xer, + Gauge_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_Gauge_tags_1, + sizeof(asn_DEF_Gauge_tags_1) + /sizeof(asn_DEF_Gauge_tags_1[0]) - 1, /* 1 */ + asn_DEF_Gauge_tags_1, /* Same as above */ + sizeof(asn_DEF_Gauge_tags_1) + /sizeof(asn_DEF_Gauge_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/GetNextRequest-PDU.c b/libs/smux/GetNextRequest-PDU.c new file mode 100644 index 00000000..4ba345e5 --- /dev/null +++ b/libs/smux/GetNextRequest-PDU.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "GetNextRequest-PDU.h" + +int +GetNextRequest_PDU_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_PDU.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using PDU, + * so here we adjust the DEF accordingly. + */ +static void +GetNextRequest_PDU_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_PDU.free_struct; + td->print_struct = asn_DEF_PDU.print_struct; + td->ber_decoder = asn_DEF_PDU.ber_decoder; + td->der_encoder = asn_DEF_PDU.der_encoder; + td->xer_decoder = asn_DEF_PDU.xer_decoder; + td->xer_encoder = asn_DEF_PDU.xer_encoder; + td->uper_decoder = asn_DEF_PDU.uper_decoder; + td->uper_encoder = asn_DEF_PDU.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_PDU.per_constraints; + td->elements = asn_DEF_PDU.elements; + td->elements_count = asn_DEF_PDU.elements_count; + td->specifics = asn_DEF_PDU.specifics; +} + +void +GetNextRequest_PDU_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + GetNextRequest_PDU_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +GetNextRequest_PDU_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + GetNextRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +GetNextRequest_PDU_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + GetNextRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +GetNextRequest_PDU_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + GetNextRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +GetNextRequest_PDU_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + GetNextRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +GetNextRequest_PDU_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + GetNextRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_GetNextRequest_PDU_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_GetNextRequest_PDU = { + "GetNextRequest-PDU", + "GetNextRequest-PDU", + GetNextRequest_PDU_free, + GetNextRequest_PDU_print, + GetNextRequest_PDU_constraint, + GetNextRequest_PDU_decode_ber, + GetNextRequest_PDU_encode_der, + GetNextRequest_PDU_decode_xer, + GetNextRequest_PDU_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_GetNextRequest_PDU_tags_1, + sizeof(asn_DEF_GetNextRequest_PDU_tags_1) + /sizeof(asn_DEF_GetNextRequest_PDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_GetNextRequest_PDU_tags_1, /* Same as above */ + sizeof(asn_DEF_GetNextRequest_PDU_tags_1) + /sizeof(asn_DEF_GetNextRequest_PDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* Defined elsewhere */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/GetRequest-PDU.c b/libs/smux/GetRequest-PDU.c new file mode 100644 index 00000000..41edc371 --- /dev/null +++ b/libs/smux/GetRequest-PDU.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "GetRequest-PDU.h" + +int +GetRequest_PDU_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_PDU.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using PDU, + * so here we adjust the DEF accordingly. + */ +static void +GetRequest_PDU_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_PDU.free_struct; + td->print_struct = asn_DEF_PDU.print_struct; + td->ber_decoder = asn_DEF_PDU.ber_decoder; + td->der_encoder = asn_DEF_PDU.der_encoder; + td->xer_decoder = asn_DEF_PDU.xer_decoder; + td->xer_encoder = asn_DEF_PDU.xer_encoder; + td->uper_decoder = asn_DEF_PDU.uper_decoder; + td->uper_encoder = asn_DEF_PDU.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_PDU.per_constraints; + td->elements = asn_DEF_PDU.elements; + td->elements_count = asn_DEF_PDU.elements_count; + td->specifics = asn_DEF_PDU.specifics; +} + +void +GetRequest_PDU_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + GetRequest_PDU_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +GetRequest_PDU_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + GetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +GetRequest_PDU_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + GetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +GetRequest_PDU_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + GetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +GetRequest_PDU_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + GetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +GetRequest_PDU_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + GetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_GetRequest_PDU_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_GetRequest_PDU = { + "GetRequest-PDU", + "GetRequest-PDU", + GetRequest_PDU_free, + GetRequest_PDU_print, + GetRequest_PDU_constraint, + GetRequest_PDU_decode_ber, + GetRequest_PDU_encode_der, + GetRequest_PDU_decode_xer, + GetRequest_PDU_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_GetRequest_PDU_tags_1, + sizeof(asn_DEF_GetRequest_PDU_tags_1) + /sizeof(asn_DEF_GetRequest_PDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_GetRequest_PDU_tags_1, /* Same as above */ + sizeof(asn_DEF_GetRequest_PDU_tags_1) + /sizeof(asn_DEF_GetRequest_PDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* Defined elsewhere */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/GetResponse-PDU.c b/libs/smux/GetResponse-PDU.c new file mode 100644 index 00000000..6dcc845c --- /dev/null +++ b/libs/smux/GetResponse-PDU.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "GetResponse-PDU.h" + +int +GetResponse_PDU_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_PDU.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using PDU, + * so here we adjust the DEF accordingly. + */ +static void +GetResponse_PDU_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_PDU.free_struct; + td->print_struct = asn_DEF_PDU.print_struct; + td->ber_decoder = asn_DEF_PDU.ber_decoder; + td->der_encoder = asn_DEF_PDU.der_encoder; + td->xer_decoder = asn_DEF_PDU.xer_decoder; + td->xer_encoder = asn_DEF_PDU.xer_encoder; + td->uper_decoder = asn_DEF_PDU.uper_decoder; + td->uper_encoder = asn_DEF_PDU.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_PDU.per_constraints; + td->elements = asn_DEF_PDU.elements; + td->elements_count = asn_DEF_PDU.elements_count; + td->specifics = asn_DEF_PDU.specifics; +} + +void +GetResponse_PDU_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + GetResponse_PDU_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +GetResponse_PDU_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + GetResponse_PDU_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +GetResponse_PDU_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + GetResponse_PDU_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +GetResponse_PDU_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + GetResponse_PDU_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +GetResponse_PDU_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + GetResponse_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +GetResponse_PDU_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + GetResponse_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_GetResponse_PDU_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (2 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_GetResponse_PDU = { + "GetResponse-PDU", + "GetResponse-PDU", + GetResponse_PDU_free, + GetResponse_PDU_print, + GetResponse_PDU_constraint, + GetResponse_PDU_decode_ber, + GetResponse_PDU_encode_der, + GetResponse_PDU_decode_xer, + GetResponse_PDU_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_GetResponse_PDU_tags_1, + sizeof(asn_DEF_GetResponse_PDU_tags_1) + /sizeof(asn_DEF_GetResponse_PDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_GetResponse_PDU_tags_1, /* Same as above */ + sizeof(asn_DEF_GetResponse_PDU_tags_1) + /sizeof(asn_DEF_GetResponse_PDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* Defined elsewhere */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/INTEGER.c b/libs/smux/INTEGER.c new file mode 100644 index 00000000..ba455f07 --- /dev/null +++ b/libs/smux/INTEGER.c @@ -0,0 +1,835 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include /* Encoder and decoder of a primitive type */ +#include + +/* + * INTEGER basic type description. + */ +static ber_tlv_tag_t asn_DEF_INTEGER_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_INTEGER = { + "INTEGER", + "INTEGER", + ASN__PRIMITIVE_TYPE_free, + INTEGER_print, + asn_generic_no_constraint, + ber_decode_primitive, + INTEGER_encode_der, + INTEGER_decode_xer, + INTEGER_encode_xer, + INTEGER_decode_uper, /* Unaligned PER decoder */ + INTEGER_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_INTEGER_tags, + sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]), + asn_DEF_INTEGER_tags, /* Same as above */ + sizeof(asn_DEF_INTEGER_tags) / sizeof(asn_DEF_INTEGER_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Encode INTEGER type using DER. + */ +asn_enc_rval_t +INTEGER_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + INTEGER_t *st = (INTEGER_t *)sptr; + + ASN_DEBUG("%s %s as INTEGER (tm=%d)", + cb?"Encoding":"Estimating", td->name, tag_mode); + + /* + * Canonicalize integer in the buffer. + * (Remove too long sign extension, remove some first 0x00 bytes) + */ + if(st->buf) { + uint8_t *buf = st->buf; + uint8_t *end1 = buf + st->size - 1; + int shift; + + /* Compute the number of superfluous leading bytes */ + for(; buf < end1; buf++) { + /* + * If the contents octets of an integer value encoding + * consist of more than one octet, then the bits of the + * first octet and bit 8 of the second octet: + * a) shall not all be ones; and + * b) shall not all be zero. + */ + switch(*buf) { + case 0x00: if((buf[1] & 0x80) == 0) + continue; + break; + case 0xff: if((buf[1] & 0x80)) + continue; + break; + } + break; + } + + /* Remove leading superfluous bytes from the integer */ + shift = buf - st->buf; + if(shift) { + uint8_t *nb = st->buf; + uint8_t *end; + + st->size -= shift; /* New size, minus bad bytes */ + end = nb + st->size; + + for(; nb < end; nb++, buf++) + *nb = *buf; + } + + } /* if(1) */ + + return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key); +} + +static const asn_INTEGER_enum_map_t *INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop); + +/* + * INTEGER specific human-readable output. + */ +static ssize_t +INTEGER__dump(asn_TYPE_descriptor_t *td, const INTEGER_t *st, asn_app_consume_bytes_f *cb, void *app_key, int plainOrXER) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; + char scratch[32]; /* Enough for 64-bit integer */ + uint8_t *buf = st->buf; + uint8_t *buf_end = st->buf + st->size; + signed long accum; + ssize_t wrote = 0; + char *p; + + /* + * Advance buf pointer until the start of the value's body. + * This will make us able to process large integers using simple case, + * when the actual value is small + * (0x0000000000abcdef would yield a fine 0x00abcdef) + */ + /* Skip the insignificant leading bytes */ + for(; buf < buf_end-1; buf++) { + switch(*buf) { + case 0x00: if((buf[1] & 0x80) == 0) continue; break; + case 0xff: if((buf[1] & 0x80) != 0) continue; break; + } + break; + } + + /* Simple case: the integer size is small */ + if((size_t)(buf_end - buf) <= sizeof(accum)) { + const asn_INTEGER_enum_map_t *el; + size_t scrsize; + int ret; + char *scr; + + if(buf == buf_end) { + accum = 0; + } else { + accum = (*buf & 0x80) ? -1 : 0; + for(; buf < buf_end; buf++) + accum = (accum << 8) | *buf; + } + + el = INTEGER_map_value2enum(specs, accum); + if(el) { + scrsize = el->enum_len + 32; + scr = (char *)alloca(scrsize); + if(plainOrXER == 0) + ret = snprintf(scr, scrsize, + "%ld (%s)", accum, el->enum_name); + else + ret = snprintf(scr, scrsize, + "<%s/>", el->enum_name); + } else if(plainOrXER && specs && specs->strict_enumeration) { + ASN_DEBUG("ASN.1 forbids dealing with " + "unknown value of ENUMERATED type"); + errno = EPERM; + return -1; + } else { + scrsize = sizeof(scratch); + scr = scratch; + ret = snprintf(scr, scrsize, "%ld", accum); + } + assert(ret > 0 && (size_t)ret < scrsize); + return (cb(scr, ret, app_key) < 0) ? -1 : ret; + } else if(plainOrXER && specs && specs->strict_enumeration) { + /* + * Here and earlier, we cannot encode the ENUMERATED values + * if there is no corresponding identifier. + */ + ASN_DEBUG("ASN.1 forbids dealing with " + "unknown value of ENUMERATED type"); + errno = EPERM; + return -1; + } + + /* Output in the long xx:yy:zz... format */ + /* TODO: replace with generic algorithm (Knuth TAOCP Vol 2, 4.3.1) */ + for(p = scratch; buf < buf_end; buf++) { + static const char *h2c = "0123456789ABCDEF"; + if((p - scratch) >= (ssize_t)(sizeof(scratch) - 4)) { + /* Flush buffer */ + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + wrote += p - scratch; + p = scratch; + } + *p++ = h2c[*buf >> 4]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x3a; /* ":" */ + } + if(p != scratch) + p--; /* Remove the last ":" */ + + wrote += p - scratch; + return (cb(scratch, p - scratch, app_key) < 0) ? -1 : wrote; +} + +/* + * INTEGER specific human-readable output. + */ +int +INTEGER_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const INTEGER_t *st = (const INTEGER_t *)sptr; + ssize_t ret; + + (void)td; + (void)ilevel; + + if(!st || !st->buf) + ret = cb("", 8, app_key); + else + ret = INTEGER__dump(td, st, cb, app_key, 0); + + return (ret < 0) ? -1 : 0; +} + +struct e2v_key { + const char *start; + const char *stop; + asn_INTEGER_enum_map_t *vemap; + unsigned int *evmap; +}; +static int +INTEGER__compar_enum2value(const void *kp, const void *am) { + const struct e2v_key *key = (const struct e2v_key *)kp; + const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am; + const char *ptr, *end, *name; + + /* Remap the element (sort by different criterion) */ + el = key->vemap + key->evmap[el - key->vemap]; + + /* Compare strings */ + for(ptr = key->start, end = key->stop, name = el->enum_name; + ptr < end; ptr++, name++) { + if(*ptr != *name) + return *(const unsigned char *)ptr + - *(const unsigned char *)name; + } + return name[0] ? -1 : 0; +} + +static const asn_INTEGER_enum_map_t * +INTEGER_map_enum2value(asn_INTEGER_specifics_t *specs, const char *lstart, const char *lstop) { + asn_INTEGER_enum_map_t *el_found; + int count = specs ? specs->map_count : 0; + struct e2v_key key; + const char *lp; + + if(!count) return NULL; + + /* Guaranteed: assert(lstart < lstop); */ + /* Figure out the tag name */ + for(lstart++, lp = lstart; lp < lstop; lp++) { + switch(*lp) { + case 9: case 10: case 11: case 12: case 13: case 32: /* WSP */ + case 0x2f: /* '/' */ case 0x3e: /* '>' */ + break; + default: + continue; + } + break; + } + if(lp == lstop) return NULL; /* No tag found */ + lstop = lp; + + key.start = lstart; + key.stop = lstop; + key.vemap = specs->value2enum; + key.evmap = specs->enum2value; + el_found = (asn_INTEGER_enum_map_t *)bsearch(&key, + specs->value2enum, count, sizeof(specs->value2enum[0]), + INTEGER__compar_enum2value); + if(el_found) { + /* Remap enum2value into value2enum */ + el_found = key.vemap + key.evmap[el_found - key.vemap]; + } + return el_found; +} + +static int +INTEGER__compar_value2enum(const void *kp, const void *am) { + long a = *(const long *)kp; + const asn_INTEGER_enum_map_t *el = (const asn_INTEGER_enum_map_t *)am; + long b = el->nat_value; + if(a < b) return -1; + else if(a == b) return 0; + else return 1; +} + +const asn_INTEGER_enum_map_t * +INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value) { + int count = specs ? specs->map_count : 0; + if(!count) return 0; + return (asn_INTEGER_enum_map_t *)bsearch(&value, specs->value2enum, + count, sizeof(specs->value2enum[0]), + INTEGER__compar_value2enum); +} + +static int +INTEGER_st_prealloc(INTEGER_t *st, int min_size) { + void *p = MALLOC(min_size + 1); + if(p) { + void *b = st->buf; + st->size = 0; + st->buf = p; + FREEMEM(b); + return 0; + } else { + return -1; + } +} + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +static enum xer_pbd_rval +INTEGER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + INTEGER_t *st = (INTEGER_t *)sptr; + long sign = 1; + long value; + const char *lp; + const char *lstart = (const char *)chunk_buf; + const char *lstop = lstart + chunk_size; + enum { + ST_SKIPSPACE, + ST_SKIPSPHEX, + ST_WAITDIGITS, + ST_DIGITS, + ST_HEXDIGIT1, + ST_HEXDIGIT2, + ST_HEXCOLON, + ST_EXTRASTUFF + } state = ST_SKIPSPACE; + + if(chunk_size) + ASN_DEBUG("INTEGER body %d 0x%2x..0x%2x", + chunk_size, *lstart, lstop[-1]); + + /* + * We may have received a tag here. It will be processed inline. + * Use strtoul()-like code and serialize the result. + */ + for(value = 0, lp = lstart; lp < lstop; lp++) { + int lv = *lp; + switch(lv) { + case 0x09: case 0x0a: case 0x0d: case 0x20: + switch(state) { + case ST_SKIPSPACE: + case ST_SKIPSPHEX: + continue; + case ST_HEXCOLON: + if(xer_is_whitespace(lp, lstop - lp)) { + lp = lstop - 1; + continue; + } + break; + default: + break; + } + break; + case 0x2d: /* '-' */ + if(state == ST_SKIPSPACE) { + sign = -1; + state = ST_WAITDIGITS; + continue; + } + break; + case 0x2b: /* '+' */ + if(state == ST_SKIPSPACE) { + state = ST_WAITDIGITS; + continue; + } + break; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: + switch(state) { + case ST_DIGITS: break; + case ST_SKIPSPHEX: /* Fall through */ + case ST_HEXDIGIT1: + value = (lv - 0x30) << 4; + state = ST_HEXDIGIT2; + continue; + case ST_HEXDIGIT2: + value += (lv - 0x30); + state = ST_HEXCOLON; + st->buf[st->size++] = value; + continue; + case ST_HEXCOLON: + return XPBD_BROKEN_ENCODING; + default: + state = ST_DIGITS; + break; + } + + { + long new_value = value * 10; + + if(new_value / 10 != value) + /* Overflow */ + return XPBD_DECODER_LIMIT; + + value = new_value + (lv - 0x30); + /* Check for two's complement overflow */ + if(value < 0) { + /* Check whether it is a LONG_MIN */ + if(sign == -1 + && (unsigned long)value + == ~((unsigned long)-1 >> 1)) { + sign = 1; + } else { + /* Overflow */ + return XPBD_DECODER_LIMIT; + } + } + } + continue; + case 0x3c: /* '<' */ + if(state == ST_SKIPSPACE) { + const asn_INTEGER_enum_map_t *el; + el = INTEGER_map_enum2value( + (asn_INTEGER_specifics_t *) + td->specifics, lstart, lstop); + if(el) { + ASN_DEBUG("Found \"%s\" => %ld", + el->enum_name, el->nat_value); + state = ST_DIGITS; + value = el->nat_value; + lp = lstop - 1; + continue; + } + ASN_DEBUG("Unknown identifier for INTEGER"); + } + return XPBD_BROKEN_ENCODING; + case 0x3a: /* ':' */ + if(state == ST_HEXCOLON) { + /* This colon is expected */ + state = ST_HEXDIGIT1; + continue; + } else if(state == ST_DIGITS) { + /* The colon here means that we have + * decoded the first two hexadecimal + * places as a decimal value. + * Switch decoding mode. */ + ASN_DEBUG("INTEGER re-evaluate as hex form"); + if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) + return XPBD_SYSTEM_FAILURE; + state = ST_SKIPSPHEX; + lp = lstart - 1; + continue; + } else { + ASN_DEBUG("state %d at %d", state, lp - lstart); + break; + } + /* [A-Fa-f] */ + case 0x41:case 0x42:case 0x43:case 0x44:case 0x45:case 0x46: + case 0x61:case 0x62:case 0x63:case 0x64:case 0x65:case 0x66: + switch(state) { + case ST_SKIPSPHEX: + case ST_SKIPSPACE: /* Fall through */ + case ST_HEXDIGIT1: + value = lv - ((lv < 0x61) ? 0x41 : 0x61); + value += 10; + value <<= 4; + state = ST_HEXDIGIT2; + continue; + case ST_HEXDIGIT2: + value += lv - ((lv < 0x61) ? 0x41 : 0x61); + value += 10; + st->buf[st->size++] = value; + state = ST_HEXCOLON; + continue; + case ST_DIGITS: + ASN_DEBUG("INTEGER re-evaluate as hex form"); + if(INTEGER_st_prealloc(st, (chunk_size/3) + 1)) + return XPBD_SYSTEM_FAILURE; + state = ST_SKIPSPHEX; + lp = lstart - 1; + continue; + default: + break; + } + break; + } + + /* Found extra non-numeric stuff */ + ASN_DEBUG("Found non-numeric 0x%2x at %d", + lv, lp - lstart); + state = ST_EXTRASTUFF; + break; + } + + switch(state) { + case ST_DIGITS: + /* Everything is cool */ + break; + case ST_HEXCOLON: + st->buf[st->size] = 0; /* Just in case termination */ + return XPBD_BODY_CONSUMED; + case ST_HEXDIGIT1: + case ST_HEXDIGIT2: + case ST_SKIPSPHEX: + return XPBD_BROKEN_ENCODING; + default: + if(xer_is_whitespace(lp, lstop - lp)) { + if(state != ST_EXTRASTUFF) + return XPBD_NOT_BODY_IGNORE; + break; + } else { + ASN_DEBUG("INTEGER: No useful digits (state %d)", + state); + return XPBD_BROKEN_ENCODING; /* No digits */ + } + break; + } + + value *= sign; /* Change sign, if needed */ + + if(asn_long2INTEGER(st, value)) + return XPBD_SYSTEM_FAILURE; + + return XPBD_BODY_CONSUMED; +} + +asn_dec_rval_t +INTEGER_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(INTEGER_t), opt_mname, + buf_ptr, size, INTEGER__xer_body_decode); +} + +asn_enc_rval_t +INTEGER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const INTEGER_t *st = (const INTEGER_t *)sptr; + asn_enc_rval_t er; + + (void)ilevel; + (void)flags; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = INTEGER__dump(td, st, cb, app_key, 1); + if(er.encoded < 0) _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + +asn_dec_rval_t +INTEGER_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rval = { RC_OK, 0 }; + INTEGER_t *st = (INTEGER_t *)*sptr; + asn_per_constraint_t *ct; + int repeat; + + (void)opt_codec_ctx; + + if(!st) { + st = (INTEGER_t *)(*sptr = CALLOC(1, sizeof(*st))); + if(!st) _ASN_DECODE_FAILED; + } + + if(!constraints) constraints = td->per_constraints; + ct = constraints ? &constraints->value : 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int inext = per_get_few_bits(pd, 1); + if(inext < 0) _ASN_DECODE_STARVED; + if(inext) ct = 0; + } + + FREEMEM(st->buf); + if(ct) { + if(ct->flags & APC_SEMI_CONSTRAINED) { + st->buf = (uint8_t *)CALLOC(1, 2); + if(!st->buf) _ASN_DECODE_FAILED; + st->size = 1; + } else if(ct->flags & APC_CONSTRAINED && ct->range_bits >= 0) { + size_t size = (ct->range_bits + 7) >> 3; + st->buf = (uint8_t *)MALLOC(1 + size + 1); + if(!st->buf) _ASN_DECODE_FAILED; + st->size = size; + } else { + st->size = 0; + } + } else { + st->size = 0; + } + + /* X.691, #12.2.2 */ + if(ct && ct->flags != APC_UNCONSTRAINED) { + /* #10.5.6 */ + ASN_DEBUG("Integer with range %d bits", ct->range_bits); + if(ct->range_bits >= 0) { + long value = per_get_few_bits(pd, ct->range_bits); + if(value < 0) _ASN_DECODE_STARVED; + ASN_DEBUG("Got value %ld + low %ld", + value, ct->lower_bound); + value += ct->lower_bound; + if(asn_long2INTEGER(st, value)) + _ASN_DECODE_FAILED; + return rval; + } + } else { + ASN_DEBUG("Decoding unconstrained integer %s", td->name); + } + + /* X.691, #12.2.3, #12.2.4 */ + do { + ssize_t len; + void *p; + int ret; + + /* Get the PER length */ + len = uper_get_length(pd, -1, &repeat); + if(len < 0) _ASN_DECODE_STARVED; + + p = REALLOC(st->buf, st->size + len + 1); + if(!p) _ASN_DECODE_FAILED; + st->buf = (uint8_t *)p; + + ret = per_get_many_bits(pd, &st->buf[st->size], 0, 8 * len); + if(ret < 0) _ASN_DECODE_STARVED; + st->size += len; + } while(repeat); + st->buf[st->size] = 0; /* JIC */ + + /* #12.2.3 */ + if(ct && ct->lower_bound) { + /* + * TODO: replace by in-place arithmetics. + */ + long value; + if(asn_INTEGER2long(st, &value)) + _ASN_DECODE_FAILED; + if(asn_long2INTEGER(st, value + ct->lower_bound)) + _ASN_DECODE_FAILED; + } + + return rval; +} + +asn_enc_rval_t +INTEGER_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_enc_rval_t er; + INTEGER_t *st = (INTEGER_t *)sptr; + const uint8_t *buf; + const uint8_t *end; + asn_per_constraint_t *ct; + long value = 0; + + if(!st || st->size == 0) _ASN_ENCODE_FAILED; + + if(!constraints) constraints = td->per_constraints; + ct = constraints ? &constraints->value : 0; + + er.encoded = 0; + + if(ct) { + int inext = 0; + if(asn_INTEGER2long(st, &value)) + _ASN_ENCODE_FAILED; + /* Check proper range */ + if(ct->flags & APC_SEMI_CONSTRAINED) { + if(value < ct->lower_bound) + inext = 1; + } else if(ct->range_bits >= 0) { + if(value < ct->lower_bound + || value > ct->upper_bound) + inext = 1; + } + ASN_DEBUG("Value %ld (%02x/%d) lb %ld ub %ld %s", + value, st->buf[0], st->size, + ct->lower_bound, ct->upper_bound, + inext ? "ext" : "fix"); + if(ct->flags & APC_EXTENSIBLE) { + if(per_put_few_bits(po, inext, 1)) + _ASN_ENCODE_FAILED; + if(inext) ct = 0; + } else if(inext) { + _ASN_ENCODE_FAILED; + } + } + + + /* X.691, #12.2.2 */ + if(ct && ct->range_bits >= 0) { + /* #10.5.6 */ + ASN_DEBUG("Encoding integer with range %d bits", + ct->range_bits); + if(per_put_few_bits(po, value - ct->lower_bound, + ct->range_bits)) + _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + if(ct && ct->lower_bound) { + ASN_DEBUG("Adjust lower bound to %ld", ct->lower_bound); + /* TODO: adjust lower bound */ + _ASN_ENCODE_FAILED; + } + + for(buf = st->buf, end = st->buf + st->size; buf < end;) { + ssize_t mayEncode = uper_put_length(po, end - buf); + if(mayEncode < 0) + _ASN_ENCODE_FAILED; + if(per_put_many_bits(po, buf, 8 * mayEncode)) + _ASN_ENCODE_FAILED; + buf += mayEncode; + } + + _ASN_ENCODED_OK(er); +} + +int +asn_INTEGER2long(const INTEGER_t *iptr, long *lptr) { + uint8_t *b, *end; + size_t size; + long l; + + /* Sanity checking */ + if(!iptr || !iptr->buf || !lptr) { + errno = EINVAL; + return -1; + } + + /* Cache the begin/end of the buffer */ + b = iptr->buf; /* Start of the INTEGER buffer */ + size = iptr->size; + end = b + size; /* Where to stop */ + + if(size > sizeof(long)) { + uint8_t *end1 = end - 1; + /* + * Slightly more advanced processing, + * able to >sizeof(long) bytes, + * when the actual value is small + * (0x0000000000abcdef would yield a fine 0x00abcdef) + */ + /* Skip out the insignificant leading bytes */ + for(; b < end1; b++) { + switch(*b) { + case 0x00: if((b[1] & 0x80) == 0) continue; break; + case 0xff: if((b[1] & 0x80) != 0) continue; break; + } + break; + } + + size = end - b; + if(size > sizeof(long)) { + /* Still cannot fit the long */ + errno = ERANGE; + return -1; + } + } + + /* Shortcut processing of a corner case */ + if(end == b) { + *lptr = 0; + return 0; + } + + /* Perform the sign initialization */ + /* Actually l = -(*b >> 7); gains nothing, yet unreadable! */ + if((*b >> 7)) l = -1; else l = 0; + + /* Conversion engine */ + for(; b < end; b++) + l = (l << 8) | *b; + + *lptr = l; + return 0; +} + +int +asn_long2INTEGER(INTEGER_t *st, long value) { + uint8_t *buf, *bp; + uint8_t *p; + uint8_t *pstart; + uint8_t *pend1; + int littleEndian = 1; /* Run-time detection */ + int add; + + if(!st) { + errno = EINVAL; + return -1; + } + + buf = (uint8_t *)MALLOC(sizeof(value)); + if(!buf) return -1; + + if(*(char *)&littleEndian) { + pstart = (uint8_t *)&value + sizeof(value) - 1; + pend1 = (uint8_t *)&value; + add = -1; + } else { + pstart = (uint8_t *)&value; + pend1 = pstart + sizeof(value) - 1; + add = 1; + } + + /* + * If the contents octet consists of more than one octet, + * then bits of the first octet and bit 8 of the second octet: + * a) shall not all be ones; and + * b) shall not all be zero. + */ + for(p = pstart; p != pend1; p += add) { + switch(*p) { + case 0x00: if((*(p+add) & 0x80) == 0) + continue; + break; + case 0xff: if((*(p+add) & 0x80)) + continue; + break; + } + break; + } + /* Copy the integer body */ + for(pstart = p, bp = buf, pend1 += add; p != pend1; p += add) + *bp++ = *p; + + if(st->buf) FREEMEM(st->buf); + st->buf = buf; + st->size = bp - buf; + + return 0; +} diff --git a/libs/smux/IfEntry.c b/libs/smux/IfEntry.c new file mode 100644 index 00000000..a97b2454 --- /dev/null +++ b/libs/smux/IfEntry.c @@ -0,0 +1,271 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "IfEntry.h" + +static asn_TYPE_member_t asn_MBR_IfEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifIndex), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifIndex" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifDescr), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_DisplayString, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifDescr" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifType), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifType" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifMtu), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifMtu" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifSpeed), + (ASN_TAG_CLASS_APPLICATION | (2 << 2)), + 0, + &asn_DEF_Gauge, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifSpeed" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifPhysAddress), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_PhysAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifPhysAddress" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifAdminStatus), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifAdminStatus" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifOperStatus), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifOperStatus" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifLastChange), + (ASN_TAG_CLASS_APPLICATION | (3 << 2)), + 0, + &asn_DEF_TimeTicks, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifLastChange" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifInOctets), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifInOctets" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifInUcastPkts), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifInUcastPkts" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifInNUcastPkts), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifInNUcastPkts" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifInDiscards), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifInDiscards" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifInErrors), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifInErrors" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifInUnknownProtos), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifInUnknownProtos" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifOutOctets), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifOutOctets" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifOutUcastPkts), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifOutUcastPkts" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifOutNUcastPkts), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifOutNUcastPkts" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifOutDiscards), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifOutDiscards" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifOutErrors), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_Counter, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifOutErrors" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifOutQLen), + (ASN_TAG_CLASS_APPLICATION | (2 << 2)), + 0, + &asn_DEF_Gauge, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifOutQLen" + }, + { ATF_NOFLAGS, 0, offsetof(struct IfEntry, ifSpecific), + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), + 0, + &asn_DEF_OBJECT_IDENTIFIER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ifSpecific" + }, +}; +static ber_tlv_tag_t asn_DEF_IfEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_IfEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 4 }, /* ifIndex at 78 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, -1, 3 }, /* ifType at 83 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 3, -2, 2 }, /* ifMtu at 85 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 6, -3, 1 }, /* ifAdminStatus at 91 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 7, -4, 0 }, /* ifOperStatus at 93 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 1, 0, 1 }, /* ifDescr at 81 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 5, -1, 0 }, /* ifPhysAddress at 89 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 21, 0, 0 }, /* ifSpecific at 121 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 9, 0, 10 }, /* ifInOctets at 97 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 10, -1, 9 }, /* ifInUcastPkts at 99 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 11, -2, 8 }, /* ifInNUcastPkts at 101 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 12, -3, 7 }, /* ifInDiscards at 103 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 13, -4, 6 }, /* ifInErrors at 105 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 14, -5, 5 }, /* ifInUnknownProtos at 107 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 15, -6, 4 }, /* ifOutOctets at 109 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 16, -7, 3 }, /* ifOutUcastPkts at 111 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 17, -8, 2 }, /* ifOutNUcastPkts at 113 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 18, -9, 1 }, /* ifOutDiscards at 115 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 19, -10, 0 }, /* ifOutErrors at 117 */ + { (ASN_TAG_CLASS_APPLICATION | (2 << 2)), 4, 0, 1 }, /* ifSpeed at 87 */ + { (ASN_TAG_CLASS_APPLICATION | (2 << 2)), 20, -1, 0 }, /* ifOutQLen at 119 */ + { (ASN_TAG_CLASS_APPLICATION | (3 << 2)), 8, 0, 0 } /* ifLastChange at 95 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_IfEntry_specs_1 = { + sizeof(struct IfEntry), + offsetof(struct IfEntry, _asn_ctx), + asn_MAP_IfEntry_tag2el_1, + 22, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_IfEntry = { + "IfEntry", + "IfEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_IfEntry_tags_1, + sizeof(asn_DEF_IfEntry_tags_1) + /sizeof(asn_DEF_IfEntry_tags_1[0]), /* 1 */ + asn_DEF_IfEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_IfEntry_tags_1) + /sizeof(asn_DEF_IfEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_IfEntry_1, + 22, /* Elements count */ + &asn_SPC_IfEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/IpAddrEntry.c b/libs/smux/IpAddrEntry.c new file mode 100644 index 00000000..2cfdd1e0 --- /dev/null +++ b/libs/smux/IpAddrEntry.c @@ -0,0 +1,126 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "IpAddrEntry.h" + +static int +memb_ipAdEntReasmMaxSize_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + value = *(const long *)sptr; + + if((value >= 0 && value <= 65535)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static asn_TYPE_member_t asn_MBR_IpAddrEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct IpAddrEntry, ipAdEntAddr), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipAdEntAddr" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpAddrEntry, ipAdEntIfIndex), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipAdEntIfIndex" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpAddrEntry, ipAdEntNetMask), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipAdEntNetMask" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpAddrEntry, ipAdEntBcastAddr), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipAdEntBcastAddr" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpAddrEntry, ipAdEntReasmMaxSize), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_NativeInteger, + memb_ipAdEntReasmMaxSize_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipAdEntReasmMaxSize" + }, +}; +static ber_tlv_tag_t asn_DEF_IpAddrEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_IpAddrEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 1, 0, 2 }, /* ipAdEntIfIndex at 177 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 3, -1, 1 }, /* ipAdEntBcastAddr at 181 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 4, -2, 0 }, /* ipAdEntReasmMaxSize at 183 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 0, 0, 1 }, /* ipAdEntAddr at 175 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 2, -1, 0 } /* ipAdEntNetMask at 179 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_IpAddrEntry_specs_1 = { + sizeof(struct IpAddrEntry), + offsetof(struct IpAddrEntry, _asn_ctx), + asn_MAP_IpAddrEntry_tag2el_1, + 5, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_IpAddrEntry = { + "IpAddrEntry", + "IpAddrEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_IpAddrEntry_tags_1, + sizeof(asn_DEF_IpAddrEntry_tags_1) + /sizeof(asn_DEF_IpAddrEntry_tags_1[0]), /* 1 */ + asn_DEF_IpAddrEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_IpAddrEntry_tags_1) + /sizeof(asn_DEF_IpAddrEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_IpAddrEntry_1, + 5, /* Elements count */ + &asn_SPC_IpAddrEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/IpAddress.c b/libs/smux/IpAddress.c new file mode 100644 index 00000000..0b073d2d --- /dev/null +++ b/libs/smux/IpAddress.c @@ -0,0 +1,129 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "IpAddress.h" + +int +IpAddress_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + size_t size; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + size = st->size; + + if(size == 4) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +/* + * This type is implemented using OCTET_STRING, + * so here we adjust the DEF accordingly. + */ +static void +IpAddress_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_OCTET_STRING.free_struct; + td->print_struct = asn_DEF_OCTET_STRING.print_struct; + td->ber_decoder = asn_DEF_OCTET_STRING.ber_decoder; + td->der_encoder = asn_DEF_OCTET_STRING.der_encoder; + td->xer_decoder = asn_DEF_OCTET_STRING.xer_decoder; + td->xer_encoder = asn_DEF_OCTET_STRING.xer_encoder; + td->uper_decoder = asn_DEF_OCTET_STRING.uper_decoder; + td->uper_encoder = asn_DEF_OCTET_STRING.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_OCTET_STRING.per_constraints; + td->elements = asn_DEF_OCTET_STRING.elements; + td->elements_count = asn_DEF_OCTET_STRING.elements_count; + td->specifics = asn_DEF_OCTET_STRING.specifics; +} + +void +IpAddress_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + IpAddress_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +IpAddress_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + IpAddress_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +IpAddress_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + IpAddress_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +IpAddress_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + IpAddress_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +IpAddress_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + IpAddress_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +IpAddress_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + IpAddress_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_IpAddress_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_IpAddress = { + "IpAddress", + "IpAddress", + IpAddress_free, + IpAddress_print, + IpAddress_constraint, + IpAddress_decode_ber, + IpAddress_encode_der, + IpAddress_decode_xer, + IpAddress_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_IpAddress_tags_1, + sizeof(asn_DEF_IpAddress_tags_1) + /sizeof(asn_DEF_IpAddress_tags_1[0]) - 1, /* 1 */ + asn_DEF_IpAddress_tags_1, /* Same as above */ + sizeof(asn_DEF_IpAddress_tags_1) + /sizeof(asn_DEF_IpAddress_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/IpNetToMediaEntry.c b/libs/smux/IpNetToMediaEntry.c new file mode 100644 index 00000000..92a723f4 --- /dev/null +++ b/libs/smux/IpNetToMediaEntry.c @@ -0,0 +1,91 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "IpNetToMediaEntry.h" + +static asn_TYPE_member_t asn_MBR_IpNetToMediaEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct IpNetToMediaEntry, ipNetToMediaIfIndex), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipNetToMediaIfIndex" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpNetToMediaEntry, ipNetToMediaPhysAddress), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_PhysAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipNetToMediaPhysAddress" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpNetToMediaEntry, ipNetToMediaNetAddress), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipNetToMediaNetAddress" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpNetToMediaEntry, ipNetToMediaType), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipNetToMediaType" + }, +}; +static ber_tlv_tag_t asn_DEF_IpNetToMediaEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_IpNetToMediaEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 1 }, /* ipNetToMediaIfIndex at 222 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 3, -1, 0 }, /* ipNetToMediaType at 229 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 1, 0, 0 }, /* ipNetToMediaPhysAddress at 224 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 2, 0, 0 } /* ipNetToMediaNetAddress at 226 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_IpNetToMediaEntry_specs_1 = { + sizeof(struct IpNetToMediaEntry), + offsetof(struct IpNetToMediaEntry, _asn_ctx), + asn_MAP_IpNetToMediaEntry_tag2el_1, + 4, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_IpNetToMediaEntry = { + "IpNetToMediaEntry", + "IpNetToMediaEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_IpNetToMediaEntry_tags_1, + sizeof(asn_DEF_IpNetToMediaEntry_tags_1) + /sizeof(asn_DEF_IpNetToMediaEntry_tags_1[0]), /* 1 */ + asn_DEF_IpNetToMediaEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_IpNetToMediaEntry_tags_1) + /sizeof(asn_DEF_IpNetToMediaEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_IpNetToMediaEntry_1, + 4, /* Elements count */ + &asn_SPC_IpNetToMediaEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/IpRouteEntry.c b/libs/smux/IpRouteEntry.c new file mode 100644 index 00000000..190f749e --- /dev/null +++ b/libs/smux/IpRouteEntry.c @@ -0,0 +1,181 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "IpRouteEntry.h" + +static asn_TYPE_member_t asn_MBR_IpRouteEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteDest), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteDest" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteIfIndex), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteIfIndex" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteMetric1), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteMetric1" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteMetric2), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteMetric2" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteMetric3), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteMetric3" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteMetric4), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteMetric4" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteNextHop), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteNextHop" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteType), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteType" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteProto), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteProto" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteAge), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteAge" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteMask), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteMask" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteMetric5), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteMetric5" + }, + { ATF_NOFLAGS, 0, offsetof(struct IpRouteEntry, ipRouteInfo), + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), + 0, + &asn_DEF_OBJECT_IDENTIFIER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "ipRouteInfo" + }, +}; +static ber_tlv_tag_t asn_DEF_IpRouteEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_IpRouteEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 1, 0, 8 }, /* ipRouteIfIndex at 192 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, -1, 7 }, /* ipRouteMetric1 at 194 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 3, -2, 6 }, /* ipRouteMetric2 at 196 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 4, -3, 5 }, /* ipRouteMetric3 at 198 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 5, -4, 4 }, /* ipRouteMetric4 at 200 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 7, -5, 3 }, /* ipRouteType at 204 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 8, -6, 2 }, /* ipRouteProto at 206 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 9, -7, 1 }, /* ipRouteAge at 208 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 11, -8, 0 }, /* ipRouteMetric5 at 212 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 12, 0, 0 }, /* ipRouteInfo at 215 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 0, 0, 2 }, /* ipRouteDest at 190 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 6, -1, 1 }, /* ipRouteNextHop at 202 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 10, -2, 0 } /* ipRouteMask at 210 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_IpRouteEntry_specs_1 = { + sizeof(struct IpRouteEntry), + offsetof(struct IpRouteEntry, _asn_ctx), + asn_MAP_IpRouteEntry_tag2el_1, + 13, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_IpRouteEntry = { + "IpRouteEntry", + "IpRouteEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_IpRouteEntry_tags_1, + sizeof(asn_DEF_IpRouteEntry_tags_1) + /sizeof(asn_DEF_IpRouteEntry_tags_1[0]), /* 1 */ + asn_DEF_IpRouteEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_IpRouteEntry_tags_1) + /sizeof(asn_DEF_IpRouteEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_IpRouteEntry_1, + 13, /* Elements count */ + &asn_SPC_IpRouteEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/Makefile b/libs/smux/Makefile new file mode 100644 index 00000000..8988da2f --- /dev/null +++ b/libs/smux/Makefile @@ -0,0 +1,22 @@ +include ../../Makefile.conf + +LIB_NAME = stgsmux + +SRCS = $(wildcard *.c) + +INCS = $(notdir $(wildcard include/stg/*.h)) + +LIB_INCS = -I ./include/stg + +#.PHONY: asn1 + +#ASN1_SOURCES = RFC1213-MIB.asn1 \ +# RFC1155-SMI.asn1 \ +# RFC1157-SNMP.asn1 \ +# SMUX.asn1 + +#asn1: $(ASN1_SOURCES) +# asn1c -fskeletons-copy -fcompound-names $^ +# rm Makefile.am.sample + +include ../Makefile.in diff --git a/libs/smux/Message.c b/libs/smux/Message.c new file mode 100644 index 00000000..545b426a --- /dev/null +++ b/libs/smux/Message.c @@ -0,0 +1,80 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "Message.h" + +static asn_TYPE_member_t asn_MBR_Message_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct Message, version), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "version" + }, + { ATF_NOFLAGS, 0, offsetof(struct Message, community), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_OCTET_STRING, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "community" + }, + { ATF_OPEN_TYPE | ATF_NOFLAGS, 0, offsetof(struct Message, data), + -1 /* Ambiguous tag (ANY?) */, + 0, + &asn_DEF_ANY, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "data" + }, +}; +static ber_tlv_tag_t asn_DEF_Message_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_Message_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* version at 18 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 1, 0, 0 } /* community at 22 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_Message_specs_1 = { + sizeof(struct Message), + offsetof(struct Message, _asn_ctx), + asn_MAP_Message_tag2el_1, + 2, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_Message = { + "Message", + "Message", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_Message_tags_1, + sizeof(asn_DEF_Message_tags_1) + /sizeof(asn_DEF_Message_tags_1[0]), /* 1 */ + asn_DEF_Message_tags_1, /* Same as above */ + sizeof(asn_DEF_Message_tags_1) + /sizeof(asn_DEF_Message_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_Message_1, + 3, /* Elements count */ + &asn_SPC_Message_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/NULL.c b/libs/smux/NULL.c new file mode 100644 index 00000000..6d3316f1 --- /dev/null +++ b/libs/smux/NULL.c @@ -0,0 +1,147 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include +#include /* Implemented in terms of BOOLEAN type */ + +/* + * NULL basic type description. + */ +static ber_tlv_tag_t asn_DEF_NULL_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (5 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NULL = { + "NULL", + "NULL", + BOOLEAN_free, + NULL_print, + asn_generic_no_constraint, + BOOLEAN_decode_ber, /* Implemented in terms of BOOLEAN */ + NULL_encode_der, /* Special handling of DER encoding */ + NULL_decode_xer, + NULL_encode_xer, + NULL_decode_uper, /* Unaligned PER decoder */ + NULL_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NULL_tags, + sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), + asn_DEF_NULL_tags, /* Same as above */ + sizeof(asn_DEF_NULL_tags) / sizeof(asn_DEF_NULL_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +asn_enc_rval_t +NULL_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t erval; + + erval.encoded = der_write_tags(td, 0, tag_mode, 0, tag, cb, app_key); + if(erval.encoded == -1) { + erval.failed_type = td; + erval.structure_ptr = ptr; + } + + _ASN_ENCODED_OK(erval); +} + +asn_enc_rval_t +NULL_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + + (void)td; + (void)sptr; + (void)ilevel; + (void)flags; + (void)cb; + (void)app_key; + + /* XMLNullValue is empty */ + er.encoded = 0; + _ASN_ENCODED_OK(er); +} + + +static enum xer_pbd_rval +NULL__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + (void)td; + (void)sptr; + + if(xer_is_whitespace(chunk_buf, chunk_size)) + return XPBD_BODY_CONSUMED; + else + return XPBD_BROKEN_ENCODING; +} + +asn_dec_rval_t +NULL_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(NULL_t), opt_mname, buf_ptr, size, + NULL__xer_body_decode); +} + +int +NULL_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(sptr) { + return (cb("", 9, app_key) < 0) ? -1 : 0; + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +asn_dec_rval_t +NULL_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + + (void)opt_codec_ctx; + (void)td; + (void)constraints; + (void)pd; + + if(!*sptr) { + *sptr = MALLOC(sizeof(NULL_t)); + if(*sptr) { + *(NULL_t *)*sptr = 0; + } else { + _ASN_DECODE_FAILED; + } + } + + /* + * NULL type does not have content octets. + */ + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} + +asn_enc_rval_t +NULL_encode_uper(asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void *sptr, asn_per_outp_t *po) { + asn_enc_rval_t er; + + (void)td; + (void)constraints; + (void)sptr; + (void)po; + + er.encoded = 0; + _ASN_ENCODED_OK(er); +} diff --git a/libs/smux/NativeEnumerated.c b/libs/smux/NativeEnumerated.c new file mode 100644 index 00000000..3486cec1 --- /dev/null +++ b/libs/smux/NativeEnumerated.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Read the NativeInteger.h for the explanation wrt. differences between + * INTEGER and NativeInteger. + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this + * implementation deals with the standard (machine-specific) representation + * of them instead of using the platform-independent buffer. + */ +#include +#include + +/* + * NativeEnumerated basic type description. + */ +static ber_tlv_tag_t asn_DEF_NativeEnumerated_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (10 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NativeEnumerated = { + "ENUMERATED", /* The ASN.1 type is still ENUMERATED */ + "ENUMERATED", + NativeInteger_free, + NativeInteger_print, + asn_generic_no_constraint, + NativeInteger_decode_ber, + NativeInteger_encode_der, + NativeInteger_decode_xer, + NativeEnumerated_encode_xer, + NativeEnumerated_decode_uper, + NativeEnumerated_encode_uper, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeEnumerated_tags, + sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), + asn_DEF_NativeEnumerated_tags, /* Same as above */ + sizeof(asn_DEF_NativeEnumerated_tags) / sizeof(asn_DEF_NativeEnumerated_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +asn_enc_rval_t +NativeEnumerated_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_INTEGER_specifics_t *specs=(asn_INTEGER_specifics_t *)td->specifics; + asn_enc_rval_t er; + const long *native = (const long *)sptr; + const asn_INTEGER_enum_map_t *el; + + (void)ilevel; + (void)flags; + + if(!native) _ASN_ENCODE_FAILED; + + el = INTEGER_map_value2enum(specs, *native); + if(el) { + size_t srcsize = el->enum_len + 5; + char *src = (char *)alloca(srcsize); + + er.encoded = snprintf(src, srcsize, "<%s/>", el->enum_name); + assert(er.encoded > 0 && (size_t)er.encoded < srcsize); + if(cb(src, er.encoded, app_key) < 0) _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } else { + ASN_DEBUG("ASN.1 forbids dealing with " + "unknown value of ENUMERATED type"); + _ASN_ENCODE_FAILED; + } +} + +asn_dec_rval_t +NativeEnumerated_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void **sptr, asn_per_data_t *pd) { + asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics; + asn_dec_rval_t rval = { RC_OK, 0 }; + long *native = (long *)*sptr; + asn_per_constraint_t *ct; + long value; + + (void)opt_codec_ctx; + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else _ASN_DECODE_FAILED; /* Mandatory! */ + if(!specs) _ASN_DECODE_FAILED; + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + ASN_DEBUG("Decoding %s as NativeEnumerated", td->name); + + if(ct->flags & APC_EXTENSIBLE) { + int inext = per_get_few_bits(pd, 1); + if(inext < 0) _ASN_DECODE_STARVED; + if(inext) ct = 0; + } + + if(ct && ct->range_bits >= 0) { + value = per_get_few_bits(pd, ct->range_bits); + if(value < 0) _ASN_DECODE_STARVED; + if(value >= (specs->extension + ? specs->extension - 1 : specs->map_count)) + _ASN_DECODE_FAILED; + } else { + if(!specs->extension) + _ASN_DECODE_FAILED; + /* + * X.691, #10.6: normally small non-negative whole number; + */ + value = uper_get_nsnnwn(pd); + if(value < 0) _ASN_DECODE_STARVED; + value += specs->extension - 1; + if(value >= specs->map_count) + _ASN_DECODE_FAILED; + } + + *native = specs->value2enum[value].nat_value; + ASN_DEBUG("Decoded %s = %ld", td->name, *native); + + return rval; +} + +static int +NativeEnumerated__compar_value2enum(const void *ap, const void *bp) { + const asn_INTEGER_enum_map_t *a = ap; + const asn_INTEGER_enum_map_t *b = bp; + if(a->nat_value == b->nat_value) + return 0; + if(a->nat_value < b->nat_value) + return -1; + return 1; +} + +asn_enc_rval_t +NativeEnumerated_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_INTEGER_specifics_t *specs = (asn_INTEGER_specifics_t *)td->specifics; + asn_enc_rval_t er; + long native, value; + asn_per_constraint_t *ct = NULL; + int inext = 0; + asn_INTEGER_enum_map_t key; + asn_INTEGER_enum_map_t *kf; + + if(!sptr) _ASN_ENCODE_FAILED; + if(!specs) _ASN_ENCODE_FAILED; + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else _ASN_ENCODE_FAILED; /* Mandatory! */ + + ASN_DEBUG("Encoding %s as NativeEnumerated", td->name); + + er.encoded = 0; + + native = *(long *)sptr; + if(native < 0) _ASN_ENCODE_FAILED; + + key.nat_value = native; + kf = bsearch(&key, specs->value2enum, specs->map_count, + sizeof(key), NativeEnumerated__compar_value2enum); + if(!kf) { + ASN_DEBUG("No element corresponds to %ld", native); + _ASN_ENCODE_FAILED; + } + value = kf - specs->value2enum; + + if(ct && ct->range_bits >= 0) { + int cmpWith = specs->extension + ? specs->extension - 1 : specs->map_count; + if(value >= cmpWith) + inext = 1; + } + if(ct && ct->flags & APC_EXTENSIBLE) { + if(per_put_few_bits(po, inext, 0)) + _ASN_ENCODE_FAILED; + ct = 0; + } else if(inext) { + _ASN_ENCODE_FAILED; + } + + if(ct && ct->range_bits >= 0) { + if(per_put_few_bits(po, value, ct->range_bits)) + _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + if(!specs->extension) + _ASN_ENCODE_FAILED; + + /* + * X.691, #10.6: normally small non-negative whole number; + */ + if(uper_put_nsnnwn(po, value - (specs->extension - 1))) + _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + diff --git a/libs/smux/NativeInteger.c b/libs/smux/NativeInteger.c new file mode 100644 index 00000000..db234c8b --- /dev/null +++ b/libs/smux/NativeInteger.c @@ -0,0 +1,313 @@ +/*- + * Copyright (c) 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Read the NativeInteger.h for the explanation wrt. differences between + * INTEGER and NativeInteger. + * Basically, both are decoders and encoders of ASN.1 INTEGER type, but this + * implementation deals with the standard (machine-specific) representation + * of them instead of using the platform-independent buffer. + */ +#include +#include + +/* + * NativeInteger basic type description. + */ +static ber_tlv_tag_t asn_DEF_NativeInteger_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_NativeInteger = { + "INTEGER", /* The ASN.1 type is still INTEGER */ + "INTEGER", + NativeInteger_free, + NativeInteger_print, + asn_generic_no_constraint, + NativeInteger_decode_ber, + NativeInteger_encode_der, + NativeInteger_decode_xer, + NativeInteger_encode_xer, + NativeInteger_decode_uper, /* Unaligned PER decoder */ + NativeInteger_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_NativeInteger_tags, + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + asn_DEF_NativeInteger_tags, /* Same as above */ + sizeof(asn_DEF_NativeInteger_tags) / sizeof(asn_DEF_NativeInteger_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + +/* + * Decode INTEGER type. + */ +asn_dec_rval_t +NativeInteger_decode_ber(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **nint_ptr, const void *buf_ptr, size_t size, int tag_mode) { + long *native = (long *)*nint_ptr; + asn_dec_rval_t rval; + ber_tlv_len_t length; + + /* + * If the structure is not there, allocate it. + */ + if(native == NULL) { + native = (long *)(*nint_ptr = CALLOC(1, sizeof(*native))); + if(native == NULL) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + } + + ASN_DEBUG("Decoding %s as INTEGER (tm=%d)", + td->name, tag_mode); + + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + /* + * ASN.1 encoded INTEGER: buf_ptr, length + * Fill the native, at the same time checking for overflow. + * If overflow occured, return with RC_FAIL. + */ + { + INTEGER_t tmp; + union { + const void *constbuf; + void *nonconstbuf; + } unconst_buf; + long l; + + unconst_buf.constbuf = buf_ptr; + tmp.buf = (uint8_t *)unconst_buf.nonconstbuf; + tmp.size = length; + + if(asn_INTEGER2long(&tmp, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; + } + + *native = l; + } + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s (%ld)", + (long)rval.consumed, (long)length, td->name, (long)*native); + + return rval; +} + +/* + * Encode the NativeInteger using the standard INTEGER type DER encoder. + */ +asn_enc_rval_t +NativeInteger_encode_der(asn_TYPE_descriptor_t *sd, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + unsigned long native = *(unsigned long *)ptr; /* Disable sign ext. */ + asn_enc_rval_t erval; + INTEGER_t tmp; + +#ifdef WORDS_BIGENDIAN /* Opportunistic optimization */ + + tmp.buf = (uint8_t *)&native; + tmp.size = sizeof(native); + +#else /* Works even if WORDS_BIGENDIAN is not set where should've been */ + uint8_t buf[sizeof(native)]; + uint8_t *p; + + /* Prepare a fake INTEGER */ + for(p = buf + sizeof(buf) - 1; p >= buf; p--, native >>= 8) + *p = native; + + tmp.buf = buf; + tmp.size = sizeof(buf); +#endif /* WORDS_BIGENDIAN */ + + /* Encode fake INTEGER */ + erval = INTEGER_encode_der(sd, &tmp, tag_mode, tag, cb, app_key); + if(erval.encoded == -1) { + assert(erval.structure_ptr == &tmp); + erval.structure_ptr = ptr; + } + return erval; +} + +/* + * Decode the chunk of XML text encoding INTEGER. + */ +asn_dec_rval_t +NativeInteger_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + asn_dec_rval_t rval; + INTEGER_t st; + void *st_ptr = (void *)&st; + long *native = (long *)*sptr; + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&st, 0, sizeof(st)); + rval = INTEGER_decode_xer(opt_codec_ctx, td, &st_ptr, + opt_mname, buf_ptr, size); + if(rval.code == RC_OK) { + long l; + if(asn_INTEGER2long(&st, &l)) { + rval.code = RC_FAIL; + rval.consumed = 0; + } else { + *native = l; + } + } else { + /* + * Cannot restart from the middle; + * there is no place to save state in the native type. + * Request a continuation from the very beginning. + */ + rval.consumed = 0; + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &st); + return rval; +} + + +asn_enc_rval_t +NativeInteger_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + char scratch[32]; /* Enough for 64-bit int */ + asn_enc_rval_t er; + const long *native = (const long *)sptr; + + (void)ilevel; + (void)flags; + + if(!native) _ASN_ENCODE_FAILED; + + er.encoded = snprintf(scratch, sizeof(scratch), "%ld", *native); + if(er.encoded <= 0 || (size_t)er.encoded >= sizeof(scratch) + || cb(scratch, er.encoded, app_key) < 0) + _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + +asn_dec_rval_t +NativeInteger_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + + asn_dec_rval_t rval; + long *native = (long *)*sptr; + INTEGER_t tmpint; + void *tmpintptr = &tmpint; + + (void)opt_codec_ctx; + ASN_DEBUG("Decoding NativeInteger %s (UPER)", td->name); + + if(!native) { + native = (long *)(*sptr = CALLOC(1, sizeof(*native))); + if(!native) _ASN_DECODE_FAILED; + } + + memset(&tmpint, 0, sizeof tmpint); + rval = INTEGER_decode_uper(opt_codec_ctx, td, constraints, + &tmpintptr, pd); + if(rval.code == RC_OK) { + if(asn_INTEGER2long(&tmpint, native)) + rval.code = RC_FAIL; + else + ASN_DEBUG("NativeInteger %s got value %ld", + td->name, *native); + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + + return rval; +} + +asn_enc_rval_t +NativeInteger_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_enc_rval_t er; + long native; + INTEGER_t tmpint; + + if(!sptr) _ASN_ENCODE_FAILED; + + native = *(long *)sptr; + + ASN_DEBUG("Encoding NativeInteger %s %ld (UPER)", td->name, native); + + memset(&tmpint, 0, sizeof(tmpint)); + if(asn_long2INTEGER(&tmpint, native)) + _ASN_ENCODE_FAILED; + er = INTEGER_encode_uper(td, constraints, &tmpint, po); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_INTEGER, &tmpint); + return er; +} + +/* + * INTEGER specific human-readable output. + */ +int +NativeInteger_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + const long *native = (const long *)sptr; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(native) { + char scratch[32]; /* Enough for 64-bit int */ + int ret = snprintf(scratch, sizeof(scratch), "%ld", *native); + assert(ret > 0 && (size_t)ret < sizeof(scratch)); + return (cb(scratch, ret, app_key) < 0) ? -1 : 0; + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +void +NativeInteger_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + + if(!td || !ptr) + return; + + ASN_DEBUG("Freeing %s as INTEGER (%d, %p, Native)", + td->name, contents_only, ptr); + + if(!contents_only) { + FREEMEM(ptr); + } +} + diff --git a/libs/smux/NetworkAddress.c b/libs/smux/NetworkAddress.c new file mode 100644 index 00000000..2d167746 --- /dev/null +++ b/libs/smux/NetworkAddress.c @@ -0,0 +1,57 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "NetworkAddress.h" + +static asn_TYPE_member_t asn_MBR_NetworkAddress_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct NetworkAddress, choice.internet), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "internet" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_NetworkAddress_tag2el_1[] = { + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 0, 0, 0 } /* internet at 113 */ +}; +static asn_CHOICE_specifics_t asn_SPC_NetworkAddress_specs_1 = { + sizeof(struct NetworkAddress), + offsetof(struct NetworkAddress, _asn_ctx), + offsetof(struct NetworkAddress, present), + sizeof(((struct NetworkAddress *)0)->present), + asn_MAP_NetworkAddress_tag2el_1, + 1, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +asn_TYPE_descriptor_t asn_DEF_NetworkAddress = { + "NetworkAddress", + "NetworkAddress", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + 0, /* No PER visible constraints */ + asn_MBR_NetworkAddress_1, + 1, /* Elements count */ + &asn_SPC_NetworkAddress_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/OBJECT_IDENTIFIER.c b/libs/smux/OBJECT_IDENTIFIER.c new file mode 100644 index 00000000..d0367f0f --- /dev/null +++ b/libs/smux/OBJECT_IDENTIFIER.c @@ -0,0 +1,725 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include /* for CHAR_BIT */ +#include + +/* + * OBJECT IDENTIFIER basic type description. + */ +static ber_tlv_tag_t asn_DEF_OBJECT_IDENTIFIER_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER = { + "OBJECT IDENTIFIER", + "OBJECT_IDENTIFIER", + ASN__PRIMITIVE_TYPE_free, + OBJECT_IDENTIFIER_print, + OBJECT_IDENTIFIER_constraint, + ber_decode_primitive, + der_encode_primitive, + OBJECT_IDENTIFIER_decode_xer, + OBJECT_IDENTIFIER_encode_xer, + 0, 0, + 0, /* Use generic outmost tag fetcher */ + asn_DEF_OBJECT_IDENTIFIER_tags, + sizeof(asn_DEF_OBJECT_IDENTIFIER_tags) + / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]), + asn_DEF_OBJECT_IDENTIFIER_tags, /* Same as above */ + sizeof(asn_DEF_OBJECT_IDENTIFIER_tags) + / sizeof(asn_DEF_OBJECT_IDENTIFIER_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + + +int +OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr; + + if(st && st->buf) { + if(st->size < 1) { + _ASN_CTFAIL(app_key, td, + "%s: at least one numerical value " + "expected (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + } else { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + return 0; +} + + +int +OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) { + unsigned LE __attribute__ ((unused)) = 1; /* Little endian (x86) */ + uint8_t *arcend = arcbuf + arclen; /* End of arc */ + unsigned int cache = 0; /* No more than 14 significant bits */ + unsigned char *rvbuf = (unsigned char *)rvbufp; + unsigned char *rvstart = rvbuf; /* Original start of the value buffer */ + int inc; /* Return value growth direction */ + + rvsize *= CHAR_BIT; /* bytes to bits */ + arclen *= 7; /* bytes to bits */ + + /* + * The arc has the number of bits + * cannot be represented using supplied return value type. + */ + if(arclen > rvsize) { + if(arclen > (rvsize + CHAR_BIT)) { + errno = ERANGE; /* Overflow */ + return -1; + } else { + /* + * Even if the number of bits in the arc representation + * is higher than the width of supplied * return value + * type, there is still possible to fit it when there + * are few unused high bits in the arc value + * representaion. + * + * Moreover, there is a possibility that the + * number could actually fit the arc space, given + * that add is negative, but we don't handle + * such "temporary lack of precision" situation here. + * May be considered as a bug. + */ + uint8_t mask = (0xff << (7-(arclen - rvsize))) & 0x7f; + if((*arcbuf & mask)) { + errno = ERANGE; /* Overflow */ + return -1; + } + /* Fool the routine computing unused bits */ + arclen -= 7; + cache = *arcbuf & 0x7f; + arcbuf++; + } + } + + /* Faster path for common size */ + if(rvsize == (CHAR_BIT * sizeof(unsigned long))) { + unsigned long accum; + /* Gather all bits into the accumulator */ + for(accum = cache; arcbuf < arcend; arcbuf++) + accum = (accum << 7) | (*arcbuf & ~0x80); + if(accum < (unsigned)-add) { + errno = ERANGE; /* Overflow */ + return -1; + } + *(unsigned long *)rvbuf = accum + add; /* alignment OK! */ + return 0; + } + +#ifndef WORDS_BIGENDIAN + if(*(unsigned char *)&LE) { /* Little endian (x86) */ + /* "Convert" to big endian */ + rvbuf += rvsize / CHAR_BIT - 1; + rvstart--; + inc = -1; /* Descending */ + } else +#endif /* !WORDS_BIGENDIAN */ + inc = +1; /* Big endian is known [at compile time] */ + + { + int bits; /* typically no more than 3-4 bits */ + + /* Clear the high unused bits */ + for(bits = rvsize - arclen; + bits > CHAR_BIT; + rvbuf += inc, bits -= CHAR_BIT) + *rvbuf = 0; + + /* Fill the body of a value */ + for(; arcbuf < arcend; arcbuf++) { + cache = (cache << 7) | (*arcbuf & 0x7f); + bits += 7; + if(bits >= CHAR_BIT) { + bits -= CHAR_BIT; + *rvbuf = (cache >> bits); + rvbuf += inc; + } + } + if(bits) { + *rvbuf = cache; + rvbuf += inc; + } + } + + if(add) { + for(rvbuf -= inc; rvbuf != rvstart; rvbuf -= inc) { + int v = add + *rvbuf; + if(v & (-1 << CHAR_BIT)) { + *rvbuf = (unsigned char)(v + (1 << CHAR_BIT)); + add = -1; + } else { + *rvbuf = v; + break; + } + } + if(rvbuf == rvstart) { + /* No space to carry over */ + errno = ERANGE; /* Overflow */ + return -1; + } + } + + return 0; +} + +ssize_t +OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add, + asn_app_consume_bytes_f *cb, void *app_key) { + char scratch[64]; /* Conservative estimate */ + unsigned long accum; /* Bits accumulator */ + + if(OBJECT_IDENTIFIER_get_single_arc(arcbuf, arclen, add, + &accum, sizeof(accum))) + return -1; + + if(accum) { + ssize_t len; + char *p = scratch + sizeof(scratch); /* Position in the scratch buffer */ + + for(; accum; accum /= 10) + *(--p) = (char)(accum % 10) + 0x30; /* Put a digit */ + + len = sizeof(scratch) - (p - scratch); + if(cb(p, len, app_key) < 0) + return -1; + return len; + } else { + *scratch = 0x30; + if(cb(scratch, 1, app_key) < 0) + return -1; + return 1; + } +} + +int +OBJECT_IDENTIFIER_print_arc(uint8_t *arcbuf, int arclen, int add, + asn_app_consume_bytes_f *cb, void *app_key) { + + if(OBJECT_IDENTIFIER__dump_arc(arcbuf, arclen, add, cb, app_key) < 0) + return -1; + + return 0; +} + +static ssize_t +OBJECT_IDENTIFIER__dump_body(const OBJECT_IDENTIFIER_t *st, asn_app_consume_bytes_f *cb, void *app_key) { + ssize_t wrote_len = 0; + int startn; + int add = 0; + int i; + + for(i = 0, startn = 0; i < st->size; i++) { + uint8_t b = st->buf[i]; + if((b & 0x80)) /* Continuation expected */ + continue; + + if(startn == 0) { + /* + * First two arcs are encoded through the backdoor. + */ + if(i) { + add = -80; + if(cb("2", 1, app_key) < 0) return -1; + } else if(b <= 39) { + add = 0; + if(cb("0", 1, app_key) < 0) return -1; + } else if(b < 79) { + add = -40; + if(cb("1", 1, app_key) < 0) return -1; + } else { + add = -80; + if(cb("2", 1, app_key) < 0) return -1; + } + wrote_len += 1; + } + + if(cb(".", 1, app_key) < 0) /* Separate arcs */ + return -1; + + add = OBJECT_IDENTIFIER__dump_arc(&st->buf[startn], + i - startn + 1, add, cb, app_key); + if(add < 0) return -1; + wrote_len += 1 + add; + startn = i + 1; + add = 0; + } + + return wrote_len; +} + +static enum xer_pbd_rval +OBJECT_IDENTIFIER__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) { + OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)sptr; + const char *chunk_end = (const char *)chunk_buf + chunk_size; + const char *endptr; + long s_arcs[10]; + long *arcs = s_arcs; + int arcs_count; + int ret; + + (void)td; + + arcs_count = OBJECT_IDENTIFIER_parse_arcs( + (const char *)chunk_buf, chunk_size, arcs, + sizeof(s_arcs)/sizeof(s_arcs[0]), &endptr); + if(arcs_count <= 0) { + /* Expecting more than zero arcs */ + return XPBD_BROKEN_ENCODING; + } + if(endptr < chunk_end) { + /* We have a tail of unrecognized data. Check its safety. */ + if(!xer_is_whitespace(endptr, chunk_end - endptr)) + return XPBD_BROKEN_ENCODING; + } + + if((size_t)arcs_count > sizeof(s_arcs)/sizeof(s_arcs[0])) { + arcs = (long *)MALLOC(arcs_count * sizeof(long)); + if(!arcs) return XPBD_SYSTEM_FAILURE; + ret = OBJECT_IDENTIFIER_parse_arcs( + (const char *)chunk_buf, chunk_size, + arcs, arcs_count, &endptr); + if(ret != arcs_count) + return XPBD_SYSTEM_FAILURE; /* assert?.. */ + } + + /* + * Convert arcs into BER representation. + */ + ret = OBJECT_IDENTIFIER_set_arcs(st, arcs, sizeof(*arcs), arcs_count); + if(arcs != s_arcs) FREEMEM(arcs); + + return ret ? XPBD_SYSTEM_FAILURE : XPBD_BODY_CONSUMED; +} + +asn_dec_rval_t +OBJECT_IDENTIFIER_decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + + return xer_decode_primitive(opt_codec_ctx, td, + sptr, sizeof(OBJECT_IDENTIFIER_t), opt_mname, + buf_ptr, size, OBJECT_IDENTIFIER__xer_body_decode); +} + +asn_enc_rval_t +OBJECT_IDENTIFIER_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr; + asn_enc_rval_t er; + + (void)ilevel; + (void)flags; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = OBJECT_IDENTIFIER__dump_body(st, cb, app_key); + if(er.encoded < 0) _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(er); +} + +int +OBJECT_IDENTIFIER_print(asn_TYPE_descriptor_t *td, const void *sptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(!st || !st->buf) + return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb("{ ", 2, app_key) < 0) + return -1; + + if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0) + return -1; + + return (cb(" }", 2, app_key) < 0) ? -1 : 0; +} + +int +OBJECT_IDENTIFIER_get_arcs(OBJECT_IDENTIFIER_t *oid, void *arcs, + unsigned int arc_type_size, unsigned int arc_slots) { + void *arcs_end = (char *)arcs + (arc_type_size * arc_slots); + int num_arcs = 0; + int startn = 0; + int add = 0; + int i; + + if(!oid || !oid->buf || (arc_slots && arc_type_size <= 1)) { + errno = EINVAL; + return -1; + } + + for(i = 0; i < oid->size; i++) { + uint8_t b = oid->buf[i]; + if((b & 0x80)) /* Continuation expected */ + continue; + + if(num_arcs == 0) { + /* + * First two arcs are encoded through the backdoor. + */ + unsigned LE = 1; /* Little endian */ + int first_arc; + num_arcs++; + if(!arc_slots) { num_arcs++; continue; } + + if(i) first_arc = 2; + else if(b <= 39) first_arc = 0; + else if(b < 79) first_arc = 1; + else first_arc = 2; + + add = -40 * first_arc; + memset(arcs, 0, arc_type_size); + *(unsigned char *)((char *)arcs + + ((*(char *)&LE)?0:(arc_type_size - 1))) + = first_arc; + arcs = ((char *)arcs) + arc_type_size; + } + + /* Decode, if has space */ + if(arcs < arcs_end) { + if(OBJECT_IDENTIFIER_get_single_arc(&oid->buf[startn], + i - startn + 1, add, + arcs, arc_type_size)) + return -1; + startn = i + 1; + arcs = ((char *)arcs) + arc_type_size; + add = 0; + } + num_arcs++; + } + + return num_arcs; +} + + +/* + * Save the single value as an object identifier arc. + */ +int +OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, const void *arcval, unsigned int arcval_size, int prepared_order) { + /* + * The following conditions must hold: + * assert(arcval); + * assert(arcval_size > 0); + * assert(arcval_size <= 16); + * assert(arcbuf); + */ +#ifdef WORDS_BIGENDIAN + const unsigned isLittleEndian = 0; +#else + unsigned LE = 1; + unsigned isLittleEndian = *(char *)&LE; +#endif + const uint8_t *tend, *tp; + unsigned int cache; + uint8_t *bp = arcbuf; + int bits; + uint8_t buffer[16]; + + if(isLittleEndian && !prepared_order) { + const uint8_t *a = (const unsigned char *)arcval + arcval_size - 1; + const uint8_t *aend = (const uint8_t *)arcval; + uint8_t *msb = buffer + arcval_size - 1; + uint8_t *tb; + for(tb = buffer; a >= aend; tb++, a--) + if((*tb = *a) && (tb < msb)) + msb = tb; + tend = &buffer[arcval_size]; + tp = msb; /* Most significant non-zero byte */ + } else { + /* Look for most significant non-zero byte */ + tend = (const unsigned char *)arcval + arcval_size; + for(tp = (const uint8_t *)arcval; tp < tend - 1; tp++) + if(*tp) break; + } + + /* + * Split the value in 7-bits chunks. + */ + bits = ((tend - tp) * CHAR_BIT) % 7; + if(bits) { + cache = *tp >> (CHAR_BIT - bits); + if(cache) { + *bp++ = cache | 0x80; + cache = *tp++; + bits = CHAR_BIT - bits; + } else { + bits = -bits; + } + } else { + cache = 0; + } + for(; tp < tend; tp++) { + cache = (cache << CHAR_BIT) + *tp; + bits += CHAR_BIT; + while(bits >= 7) { + bits -= 7; + *bp++ = 0x80 | (cache >> bits); + } + } + if(bits) *bp++ = cache; + bp[-1] &= 0x7f; /* Clear the last bit */ + + return bp - arcbuf; +} + +int +OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *oid, const void *arcs, unsigned int arc_type_size, unsigned int arc_slots) { + uint8_t *buf; + uint8_t *bp; + unsigned LE = 1; /* Little endian (x86) */ + unsigned isLittleEndian = *((char *)&LE); + unsigned int arc0; + unsigned int arc1; + unsigned size; + unsigned i; + + if(!oid || !arcs || arc_type_size < 1 + || arc_type_size > 16 + || arc_slots < 2) { + errno = EINVAL; + return -1; + } + + switch(arc_type_size) { + case sizeof(char): + arc0 = ((const unsigned char *)arcs)[0]; + arc1 = ((const unsigned char *)arcs)[1]; + break; + case sizeof(short): + arc0 = ((const unsigned short *)arcs)[0]; + arc1 = ((const unsigned short *)arcs)[1]; + break; + case sizeof(int): + arc0 = ((const unsigned int *)arcs)[0]; + arc1 = ((const unsigned int *)arcs)[1]; + break; + default: + arc1 = arc0 = 0; + if(isLittleEndian) { /* Little endian (x86) */ + const unsigned char *ps, *pe; + /* If more significant bytes are present, + * make them > 255 quick */ + for(ps = (const unsigned char *)arcs + 1, pe = ps+arc_type_size; + ps < pe; ps++) + arc0 |= *ps, arc1 |= *(ps + arc_type_size); + arc0 <<= CHAR_BIT, arc1 <<= CHAR_BIT; + arc0 = *((const unsigned char *)arcs + 0); + arc1 = *((const unsigned char *)arcs + arc_type_size); + } else { + const unsigned char *ps, *pe; + /* If more significant bytes are present, + * make them > 255 quick */ + for(ps = (const unsigned char *)arcs, pe = ps+arc_type_size - 1; ps < pe; ps++) + arc0 |= *ps, arc1 |= *(ps + arc_type_size); + arc0 = *((const unsigned char *)arcs + arc_type_size - 1); + arc1 = *((const unsigned char *)arcs +(arc_type_size<< 1)-1); + } + } + + /* + * The previous chapter left us with the first and the second arcs. + * The values are not precise (that is, they are valid only if + * they're less than 255), but OK for the purposes of making + * the sanity test below. + */ + if(arc0 <= 1) { + if(arc1 >= 39) { + /* 8.19.4: At most 39 subsequent values (including 0) */ + errno = ERANGE; + return -1; + } + } else if(arc0 > 2) { + /* 8.19.4: Only three values are allocated from the root node */ + errno = ERANGE; + return -1; + } + /* + * After above tests it is known that the value of arc0 is completely + * trustworthy (0..2). However, the arc1's value is still meaningless. + */ + + /* + * Roughly estimate the maximum size necessary to encode these arcs. + * This estimation implicitly takes in account the following facts, + * that cancel each other: + * * the first two arcs are encoded in a single value. + * * the first value may require more space (+1 byte) + * * the value of the first arc which is in range (0..2) + */ + size = ((arc_type_size * CHAR_BIT + 6) / 7) * arc_slots; + bp = buf = (uint8_t *)MALLOC(size + 1); + if(!buf) { + /* ENOMEM */ + return -1; + } + + /* + * Encode the first two arcs. + * These require special treatment. + */ + { + uint8_t *tp; + uint8_t first_value[1 + 16]; /* of two arcs */ + uint8_t *fv = first_value; + + /* + * Simulate first_value = arc0 * 40 + arc1; + */ + /* Copy the second (1'st) arcs[1] into the first_value */ + *fv++ = 0; + arcs = ((const char *)arcs) + arc_type_size; + if(isLittleEndian) { + const uint8_t *aend = (const unsigned char *)arcs - 1; + const uint8_t *a1 = (const unsigned char *)arcs + arc_type_size - 1; + for(; a1 > aend; fv++, a1--) *fv = *a1; + } else { + const uint8_t *a1 = (const uint8_t *)arcs; + const uint8_t *aend = a1 + arc_type_size; + for(; a1 < aend; fv++, a1++) *fv = *a1; + } + /* Increase the first_value by arc0 */ + arc0 *= 40; /* (0..80) */ + for(tp = first_value + arc_type_size; tp >= first_value; tp--) { + unsigned int v = *tp; + v += arc0; + *tp = v; + if(v >= (1 << CHAR_BIT)) arc0 = v >> CHAR_BIT; + else break; + } + + assert(tp >= first_value); + + bp += OBJECT_IDENTIFIER_set_single_arc(bp, first_value, + fv - first_value, 1); + } + + /* + * Save the rest of arcs. + */ + for(arcs = ((const char *)arcs) + arc_type_size, i = 2; + i < arc_slots; + i++, arcs = ((const char *)arcs) + arc_type_size) { + bp += OBJECT_IDENTIFIER_set_single_arc(bp, + arcs, arc_type_size, 0); + } + + assert((unsigned)(bp - buf) <= size); + + /* + * Replace buffer. + */ + oid->size = bp - buf; + bp = oid->buf; + oid->buf = buf; + if(bp) FREEMEM(bp); + + return 0; +} + + +int +OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, + long *arcs, unsigned int arcs_slots, const char **opt_oid_text_end) { + unsigned int arcs_count = 0; + const char *oid_end; + long value = 0; + enum { + ST_SKIPSPACE, + ST_WAITDIGITS, /* Next character is expected to be a digit */ + ST_DIGITS + } state = ST_SKIPSPACE; + + if(!oid_text || oid_txt_length < -1 || (arcs_slots && !arcs)) { + if(opt_oid_text_end) *opt_oid_text_end = oid_text; + errno = EINVAL; + return -1; + } + + if(oid_txt_length == -1) + oid_txt_length = strlen(oid_text); + + for(oid_end = oid_text + oid_txt_length; oid_text. + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include /* for .bits_unused member */ +#include + +/* + * OCTET STRING basic type description. + */ +static ber_tlv_tag_t asn_DEF_OCTET_STRING_tags[] = { + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) +}; +static asn_OCTET_STRING_specifics_t asn_DEF_OCTET_STRING_specs = { + sizeof(OCTET_STRING_t), + offsetof(OCTET_STRING_t, _asn_ctx), + 0 +}; +static asn_per_constraint_t asn_DEF_OCTET_STRING_constraint = { + APC_SEMI_CONSTRAINED, -1, -1, 0, 0 +}; +asn_TYPE_descriptor_t asn_DEF_OCTET_STRING = { + "OCTET STRING", /* Canonical name */ + "OCTET_STRING", /* XML tag name */ + OCTET_STRING_free, + OCTET_STRING_print, /* non-ascii stuff, generally */ + asn_generic_no_constraint, + OCTET_STRING_decode_ber, + OCTET_STRING_encode_der, + OCTET_STRING_decode_xer_hex, + OCTET_STRING_encode_xer, + OCTET_STRING_decode_uper, /* Unaligned PER decoder */ + OCTET_STRING_encode_uper, /* Unaligned PER encoder */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_OCTET_STRING_tags, + sizeof(asn_DEF_OCTET_STRING_tags) + / sizeof(asn_DEF_OCTET_STRING_tags[0]), + asn_DEF_OCTET_STRING_tags, /* Same as above */ + sizeof(asn_DEF_OCTET_STRING_tags) + / sizeof(asn_DEF_OCTET_STRING_tags[0]), + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + &asn_DEF_OCTET_STRING_specs +}; + +#undef _CH_PHASE +#undef NEXT_PHASE +#undef PREV_PHASE +#define _CH_PHASE(ctx, inc) do { \ + if(ctx->phase == 0) \ + ctx->context = 0; \ + ctx->phase += inc; \ + } while(0) +#define NEXT_PHASE(ctx) _CH_PHASE(ctx, +1) +#define PREV_PHASE(ctx) _CH_PHASE(ctx, -1) + +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = (num_bytes); \ + buf_ptr = ((const char *)buf_ptr) + num; \ + size -= num; \ + consumed_myself += num; \ + } while(0) + +#undef RETURN +#define RETURN(_code) do { \ + asn_dec_rval_t tmprval; \ + tmprval.code = _code; \ + tmprval.consumed = consumed_myself; \ + return tmprval; \ + } while(0) + +#undef APPEND +#define APPEND(bufptr, bufsize) do { \ + size_t _bs = (bufsize); /* Append size */ \ + size_t _ns = ctx->context; /* Allocated now */ \ + size_t _es = st->size + _bs; /* Expected size */ \ + /* int is really a typeof(st->size): */ \ + if((int)_es < 0) RETURN(RC_FAIL); \ + if(_ns <= _es) { \ + void *ptr; \ + /* Be nice and round to the memory allocator */ \ + do { _ns = _ns ? _ns << 1 : 16; } \ + while(_ns <= _es); \ + /* int is really a typeof(st->size): */ \ + if((int)_ns < 0) RETURN(RC_FAIL); \ + ptr = REALLOC(st->buf, _ns); \ + if(ptr) { \ + st->buf = (uint8_t *)ptr; \ + ctx->context = _ns; \ + } else { \ + RETURN(RC_FAIL); \ + } \ + ASN_DEBUG("Reallocating into %ld", (long)_ns); \ + } \ + memcpy(st->buf + st->size, bufptr, _bs); \ + /* Convenient nul-termination */ \ + st->buf[_es] = '\0'; \ + st->size = _es; \ + } while(0) + +/* + * Internal variant of the OCTET STRING. + */ +typedef enum OS_type { + _TT_GENERIC = 0, /* Just a random OCTET STRING */ + _TT_BIT_STRING = 1, /* BIT STRING type, a special case */ + _TT_ANY = 2 /* ANY type, a special case too */ +} OS_type_e; + +/* + * The main reason why ASN.1 is still alive is that too much time and effort + * is necessary for learning it more or less adequately, thus creating a gut + * necessity to demonstrate that aquired skill everywhere afterwards. + * No, I am not going to explain what the following stuff is. + */ +struct _stack_el { + ber_tlv_len_t left; /* What's left to read (or -1) */ + ber_tlv_len_t got; /* What was actually processed */ + int cont_level; /* Depth of subcontainment */ + int want_nulls; /* Want null "end of content" octets? */ + int bits_chopped; /* Flag in BIT STRING mode */ + ber_tlv_tag_t tag; /* For debugging purposes */ + struct _stack_el *prev; + struct _stack_el *next; +}; +struct _stack { + struct _stack_el *tail; + struct _stack_el *cur_ptr; +}; + +static struct _stack_el * +OS__add_stack_el(struct _stack *st) { + struct _stack_el *nel; + + /* + * Reuse the old stack frame or allocate a new one. + */ + if(st->cur_ptr && st->cur_ptr->next) { + nel = st->cur_ptr->next; + nel->bits_chopped = 0; + nel->got = 0; + /* Retain the nel->cont_level, it's correct. */ + } else { + nel = (struct _stack_el *)CALLOC(1, sizeof(struct _stack_el)); + if(nel == NULL) + return NULL; + + if(st->tail) { + /* Increase a subcontainment depth */ + nel->cont_level = st->tail->cont_level + 1; + st->tail->next = nel; + } + nel->prev = st->tail; + st->tail = nel; + } + + st->cur_ptr = nel; + + return nel; +} + +static struct _stack * +_new_stack() { + return (struct _stack *)CALLOC(1, sizeof(struct _stack)); +} + +/* + * Decode OCTET STRING type. + */ +asn_dec_rval_t +OCTET_STRING_decode_ber(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **sptr, const void *buf_ptr, size_t size, int tag_mode) { + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + BIT_STRING_t *st = (BIT_STRING_t *)*sptr; + asn_dec_rval_t rval; + asn_struct_ctx_t *ctx; + ssize_t consumed_myself = 0; + struct _stack *stck; /* Expectations stack structure */ + struct _stack_el *sel = 0; /* Stack element */ + int tlv_constr; + OS_type_e type_variant = (OS_type_e)specs->subvariant; + + ASN_DEBUG("Decoding %s as %s (frame %ld)", + td->name, + (type_variant == _TT_GENERIC) ? + "OCTET STRING" : "OS-SpecialCase", + (long)size); + + /* + * Create the string if does not exist. + */ + if(st == NULL) { + st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); + if(st == NULL) RETURN(RC_FAIL); + } + + /* Restore parsing context */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + switch(ctx->phase) { + case 0: + /* + * Check tags. + */ + rval = ber_check_tags(opt_codec_ctx, td, ctx, + buf_ptr, size, tag_mode, -1, + &ctx->left, &tlv_constr); + if(rval.code != RC_OK) + return rval; + + if(tlv_constr) { + /* + * Complex operation, requires stack of expectations. + */ + ctx->ptr = _new_stack(); + if(ctx->ptr) { + stck = (struct _stack *)ctx->ptr; + } else { + RETURN(RC_FAIL); + } + } else { + /* + * Jump into stackless primitive decoding. + */ + _CH_PHASE(ctx, 3); + if(type_variant == _TT_ANY && tag_mode != 1) + APPEND(buf_ptr, rval.consumed); + ADVANCE(rval.consumed); + goto phase3; + } + + NEXT_PHASE(ctx); + /* Fall through */ + case 1: + phase1: + /* + * Fill the stack with expectations. + */ + stck = (struct _stack *)ctx->ptr; + sel = stck->cur_ptr; + do { + ber_tlv_tag_t tlv_tag; + ber_tlv_len_t tlv_len; + ber_tlv_tag_t expected_tag; + ssize_t tl, ll, tlvl; + /* This one works even if (sel->left == -1) */ + ssize_t Left = ((!sel||(size_t)sel->left >= size) + ?(ssize_t)size:sel->left); + + + ASN_DEBUG("%p, s->l=%ld, s->wn=%ld, s->g=%ld\n", sel, + (long)(sel?sel->left:0), + (long)(sel?sel->want_nulls:0), + (long)(sel?sel->got:0) + ); + if(sel && sel->left <= 0 && sel->want_nulls == 0) { + if(sel->prev) { + struct _stack_el *prev = sel->prev; + if(prev->left != -1) { + if(prev->left < sel->got) + RETURN(RC_FAIL); + prev->left -= sel->got; + } + prev->got += sel->got; + sel = stck->cur_ptr = prev; + if(!sel) break; + tlv_constr = 1; + continue; + } else { + sel = stck->cur_ptr = 0; + break; /* Nothing to wait */ + } + } + + tl = ber_fetch_tag(buf_ptr, Left, &tlv_tag); + ASN_DEBUG("fetch tag(size=%ld,L=%ld), %sstack, left=%ld, wn=%ld, tl=%ld", + (long)size, (long)Left, sel?"":"!", + (long)(sel?sel->left:0), + (long)(sel?sel->want_nulls:0), + (long)tl); + switch(tl) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + tlv_constr = BER_TLV_CONSTRUCTED(buf_ptr); + + ll = ber_fetch_length(tlv_constr, + (const char *)buf_ptr + tl,Left - tl,&tlv_len); + ASN_DEBUG("Got tag=%s, tc=%d, left=%ld, tl=%ld, len=%ld, ll=%ld", + ber_tlv_tag_string(tlv_tag), tlv_constr, + (long)Left, (long)tl, (long)tlv_len, (long)ll); + switch(ll) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + if(sel && sel->want_nulls + && ((const uint8_t *)buf_ptr)[0] == 0 + && ((const uint8_t *)buf_ptr)[1] == 0) + { + + ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls); + + if(type_variant == _TT_ANY + && (tag_mode != 1 || sel->cont_level)) + APPEND("\0\0", 2); + + ADVANCE(2); + sel->got += 2; + if(sel->left != -1) { + sel->left -= 2; /* assert(sel->left >= 2) */ + } + + sel->want_nulls--; + if(sel->want_nulls == 0) { + /* Move to the next expectation */ + sel->left = 0; + tlv_constr = 1; + } + + continue; + } + + /* + * Set up expected tags, + * depending on ASN.1 type being decoded. + */ + switch(type_variant) { + case _TT_BIT_STRING: + /* X.690: 8.6.4.1, NOTE 2 */ + /* Fall through */ + case _TT_GENERIC: + default: + if(sel) { + int level = sel->cont_level; + if(level < td->all_tags_count) { + expected_tag = td->all_tags[level]; + break; + } else if(td->all_tags_count) { + expected_tag = td->all_tags + [td->all_tags_count - 1]; + break; + } + /* else, Fall through */ + } + /* Fall through */ + case _TT_ANY: + expected_tag = tlv_tag; + break; + } + + + if(tlv_tag != expected_tag) { + char buf[2][32]; + ber_tlv_tag_snprint(tlv_tag, + buf[0], sizeof(buf[0])); + ber_tlv_tag_snprint(td->tags[td->tags_count-1], + buf[1], sizeof(buf[1])); + ASN_DEBUG("Tag does not match expectation: %s != %s", + buf[0], buf[1]); + RETURN(RC_FAIL); + } + + tlvl = tl + ll; /* Combined length of T and L encoding */ + if((tlv_len + tlvl) < 0) { + /* tlv_len value is too big */ + ASN_DEBUG("TLV encoding + length (%ld) is too big", + (long)tlv_len); + RETURN(RC_FAIL); + } + + /* + * Append a new expectation. + */ + sel = OS__add_stack_el(stck); + if(!sel) RETURN(RC_FAIL); + + sel->tag = tlv_tag; + + sel->want_nulls = (tlv_len==-1); + if(sel->prev && sel->prev->left != -1) { + /* Check that the parent frame is big enough */ + if(sel->prev->left < tlvl + (tlv_len==-1?0:tlv_len)) + RETURN(RC_FAIL); + if(tlv_len == -1) + sel->left = sel->prev->left - tlvl; + else + sel->left = tlv_len; + } else { + sel->left = tlv_len; + } + if(type_variant == _TT_ANY + && (tag_mode != 1 || sel->cont_level)) + APPEND(buf_ptr, tlvl); + sel->got += tlvl; + ADVANCE(tlvl); + + ASN_DEBUG("+EXPECT2 got=%ld left=%ld, wn=%d, clvl=%d", + (long)sel->got, (long)sel->left, + sel->want_nulls, sel->cont_level); + + } while(tlv_constr); + if(sel == NULL) { + /* Finished operation, "phase out" */ + ASN_DEBUG("Phase out"); + _CH_PHASE(ctx, +3); + break; + } + + NEXT_PHASE(ctx); + /* Fall through */ + case 2: + stck = (struct _stack *)ctx->ptr; + sel = stck->cur_ptr; + ASN_DEBUG("Phase 2: Need %ld bytes, size=%ld, alrg=%ld, wn=%d", + (long)sel->left, (long)size, (long)sel->got, + sel->want_nulls); + { + ber_tlv_len_t len; + + assert(sel->left >= 0); + + len = ((ber_tlv_len_t)size < sel->left) + ? (ber_tlv_len_t)size : sel->left; + if(len > 0) { + if(type_variant == _TT_BIT_STRING + && sel->bits_chopped == 0) { + /* Put the unused-bits-octet away */ + st->bits_unused = *(const uint8_t *)buf_ptr; + APPEND(((const char *)buf_ptr+1), (len - 1)); + sel->bits_chopped = 1; + } else { + APPEND(buf_ptr, len); + } + ADVANCE(len); + sel->left -= len; + sel->got += len; + } + + if(sel->left) { + ASN_DEBUG("OS left %ld, size = %ld, wn=%d\n", + (long)sel->left, (long)size, sel->want_nulls); + RETURN(RC_WMORE); + } + + PREV_PHASE(ctx); + goto phase1; + } + break; + case 3: + phase3: + /* + * Primitive form, no stack required. + */ + assert(ctx->left >= 0); + + if(size < (size_t)ctx->left) { + if(!size) RETURN(RC_WMORE); + if(type_variant == _TT_BIT_STRING && !ctx->context) { + st->bits_unused = *(const uint8_t *)buf_ptr; + ctx->left--; + ADVANCE(1); + } + APPEND(buf_ptr, size); + assert(ctx->context > 0); + ctx->left -= size; + ADVANCE(size); + RETURN(RC_WMORE); + } else { + if(type_variant == _TT_BIT_STRING + && !ctx->context && ctx->left) { + st->bits_unused = *(const uint8_t *)buf_ptr; + ctx->left--; + ADVANCE(1); + } + APPEND(buf_ptr, ctx->left); + ADVANCE(ctx->left); + ctx->left = 0; + + NEXT_PHASE(ctx); + } + break; + } + + if(sel) { + ASN_DEBUG("3sel p=%p, wn=%d, l=%ld, g=%ld, size=%ld", + sel->prev, sel->want_nulls, + (long)sel->left, (long)sel->got, (long)size); + if(sel->prev || sel->want_nulls > 1 || sel->left > 0) { + RETURN(RC_WMORE); + } + } + + /* + * BIT STRING-specific processing. + */ + if(type_variant == _TT_BIT_STRING && st->size) { + /* Finalize BIT STRING: zero out unused bits. */ + st->buf[st->size-1] &= 0xff << st->bits_unused; + } + + ASN_DEBUG("Took %ld bytes to encode %s: [%s]:%ld", + (long)consumed_myself, td->name, + (type_variant == _TT_GENERIC) ? (char *)st->buf : "", + (long)st->size); + + + RETURN(RC_OK); +} + +/* + * Encode OCTET STRING type using DER. + */ +asn_enc_rval_t +OCTET_STRING_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + BIT_STRING_t *st = (BIT_STRING_t *)sptr; + OS_type_e type_variant = (OS_type_e)specs->subvariant; + int fix_last_byte = 0; + + ASN_DEBUG("%s %s as OCTET STRING", + cb?"Estimating":"Encoding", td->name); + + /* + * Write tags. + */ + if(type_variant != _TT_ANY || tag_mode == 1) { + er.encoded = der_write_tags(td, + (type_variant == _TT_BIT_STRING) + st->size, + tag_mode, type_variant == _TT_ANY, tag, cb, app_key); + if(er.encoded == -1) { + er.failed_type = td; + er.structure_ptr = sptr; + return er; + } + } else { + /* Disallow: [] IMPLICIT ANY */ + assert(type_variant != _TT_ANY || tag_mode != -1); + er.encoded = 0; + } + + if(!cb) { + er.encoded += (type_variant == _TT_BIT_STRING) + st->size; + _ASN_ENCODED_OK(er); + } + + /* + * Prepare to deal with the last octet of BIT STRING. + */ + if(type_variant == _TT_BIT_STRING) { + uint8_t b = st->bits_unused & 0x07; + if(b && st->size) fix_last_byte = 1; + _ASN_CALLBACK(&b, 1); + er.encoded++; + } + + /* Invoke callback for the main part of the buffer */ + _ASN_CALLBACK(st->buf, st->size - fix_last_byte); + + /* The last octet should be stripped off the unused bits */ + if(fix_last_byte) { + uint8_t b = st->buf[st->size-1] & (0xff << st->bits_unused); + _ASN_CALLBACK(&b, 1); + } + + er.encoded += st->size; + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +asn_enc_rval_t +OCTET_STRING_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + static const char *h2c = "0123456789ABCDEF"; + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + asn_enc_rval_t er; + char scratch[16 * 3 + 4]; + char *p = scratch; + uint8_t *buf; + uint8_t *end; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + /* + * Dump the contents of the buffer in hexadecimal. + */ + buf = st->buf; + end = buf + st->size; + if(flags & XER_F_CANONICAL) { + char *scend = scratch + (sizeof(scratch) - 2); + for(; buf < end; buf++) { + if(p >= scend) { + _ASN_CALLBACK(scratch, p - scratch); + er.encoded += p - scratch; + p = scratch; + } + *p++ = h2c[(*buf >> 4) & 0x0F]; + *p++ = h2c[*buf & 0x0F]; + } + + _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */ + er.encoded += p - scratch; + } else { + size_t i; + for(i = 0; buf < end; buf++, i++) { + if(!(i % 16) && (i || st->size > 16)) { + _ASN_CALLBACK(scratch, p-scratch); + er.encoded += (p-scratch); + p = scratch; + _i_ASN_TEXT_INDENT(1, ilevel); + } + *p++ = h2c[(*buf >> 4) & 0x0F]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x20; + } + if(p - scratch) { + p--; /* Remove the tail space */ + _ASN_CALLBACK(scratch, p-scratch); /* Dump the rest */ + er.encoded += p - scratch; + if(st->size > 16) + _i_ASN_TEXT_INDENT(1, ilevel-1); + } + } + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +static struct OCTET_STRING__xer_escape_table_s { + char *string; + int size; +} OCTET_STRING__xer_escape_table[] = { +#define OSXET(s) { s, sizeof(s) - 1 } + OSXET("\074\156\165\154\057\076"), /* */ + OSXET("\074\163\157\150\057\076"), /* */ + OSXET("\074\163\164\170\057\076"), /* */ + OSXET("\074\145\164\170\057\076"), /* */ + OSXET("\074\145\157\164\057\076"), /* */ + OSXET("\074\145\156\161\057\076"), /* */ + OSXET("\074\141\143\153\057\076"), /* */ + OSXET("\074\142\145\154\057\076"), /* */ + OSXET("\074\142\163\057\076"), /* */ + OSXET("\011"), /* \t */ + OSXET("\012"), /* \n */ + OSXET("\074\166\164\057\076"), /* */ + OSXET("\074\146\146\057\076"), /* */ + OSXET("\015"), /* \r */ + OSXET("\074\163\157\057\076"), /* */ + OSXET("\074\163\151\057\076"), /* */ + OSXET("\074\144\154\145\057\076"), /* */ + OSXET("\074\144\143\061\057\076"), /* */ + OSXET("\074\144\143\062\057\076"), /* */ + OSXET("\074\144\143\063\057\076"), /* */ + OSXET("\074\144\143\064\057\076"), /* */ + OSXET("\074\156\141\153\057\076"), /* */ + OSXET("\074\163\171\156\057\076"), /* */ + OSXET("\074\145\164\142\057\076"), /* */ + OSXET("\074\143\141\156\057\076"), /* */ + OSXET("\074\145\155\057\076"), /* */ + OSXET("\074\163\165\142\057\076"), /* */ + OSXET("\074\145\163\143\057\076"), /* */ + OSXET("\074\151\163\064\057\076"), /* */ + OSXET("\074\151\163\063\057\076"), /* */ + OSXET("\074\151\163\062\057\076"), /* */ + OSXET("\074\151\163\061\057\076"), /* */ + { 0, 0 }, /* " " */ + { 0, 0 }, /* ! */ + { 0, 0 }, /* \" */ + { 0, 0 }, /* # */ + { 0, 0 }, /* $ */ + { 0, 0 }, /* % */ + OSXET("\046\141\155\160\073"), /* & */ + { 0, 0 }, /* ' */ + {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* ()*+,-./ */ + {0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, /* 01234567 */ + {0,0},{0,0},{0,0},{0,0}, /* 89:; */ + OSXET("\046\154\164\073"), /* < */ + { 0, 0 }, /* = */ + OSXET("\046\147\164\073"), /* > */ +}; + +static int +OS__check_escaped_control_char(const void *buf, int size) { + size_t i; + /* + * Inefficient algorithm which translates the escape sequences + * defined above into characters. Returns -1 if not found. + * TODO: replace by a faster algorithm (bsearch(), hash or + * nested table lookups). + */ + for(i = 0; i < 32 /* Don't spend time on the bottom half */; i++) { + struct OCTET_STRING__xer_escape_table_s *el; + el = &OCTET_STRING__xer_escape_table[i]; + if(el->size == size && memcmp(buf, el->string, size) == 0) + return i; + } + return -1; +} + +static int +OCTET_STRING__handle_control_chars(void *struct_ptr, const void *chunk_buf, size_t chunk_size) { + /* + * This might be one of the escape sequences + * for control characters. Check it out. + * #11.15.5 + */ + int control_char = OS__check_escaped_control_char(chunk_buf,chunk_size); + if(control_char >= 0) { + OCTET_STRING_t *st = (OCTET_STRING_t *)struct_ptr; + void *p = REALLOC(st->buf, st->size + 2); + if(p) { + st->buf = (uint8_t *)p; + st->buf[st->size++] = control_char; + st->buf[st->size] = '\0'; /* nul-termination */ + return 0; + } + } + + return -1; /* No, it's not */ +} + +asn_enc_rval_t +OCTET_STRING_encode_xer_utf8(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + asn_enc_rval_t er; + uint8_t *buf, *end; + uint8_t *ss; /* Sequence start */ + ssize_t encoded_len = 0; + + (void)ilevel; /* Unused argument */ + (void)flags; /* Unused argument */ + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + + buf = st->buf; + end = buf + st->size; + for(ss = buf; buf < end; buf++) { + unsigned int ch = *buf; + int s_len; /* Special encoding sequence length */ + + /* + * Escape certain characters: X.680/11.15 + */ + if(ch < sizeof(OCTET_STRING__xer_escape_table) + /sizeof(OCTET_STRING__xer_escape_table[0]) + && (s_len = OCTET_STRING__xer_escape_table[ch].size)) { + if(((buf - ss) && cb(ss, buf - ss, app_key) < 0) + || cb(OCTET_STRING__xer_escape_table[ch].string, s_len, + app_key) < 0) + _ASN_ENCODE_FAILED; + encoded_len += (buf - ss) + s_len; + ss = buf + 1; + } + } + + encoded_len += (buf - ss); + if((buf - ss) && cb(ss, buf - ss, app_key) < 0) + _ASN_ENCODE_FAILED; + + er.encoded = encoded_len; + _ASN_ENCODED_OK(er); +} + +/* + * Convert from hexadecimal format (cstring): "AB CD EF" + */ +static ssize_t OCTET_STRING__convert_hexadecimal(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; + const char *chunk_stop = (const char *)chunk_buf; + const char *p = chunk_stop; + const char *pend = p + chunk_size; + unsigned int clv = 0; + int half = 0; /* Half bit */ + uint8_t *buf; + + /* Reallocate buffer according to high cap estimation */ + ssize_t _ns = st->size + (chunk_size + 1) / 2; + void *nptr = REALLOC(st->buf, _ns + 1); + if(!nptr) return -1; + st->buf = (uint8_t *)nptr; + buf = st->buf + st->size; + + /* + * If something like " a b c " appears here, the " a b":3 will be + * converted, and the rest skipped. That is, unless buf_size is greater + * than chunk_size, then it'll be equivalent to "ABC0". + */ + for(; p < pend; p++) { + int ch = *(const unsigned char *)p; + switch(ch) { + case 0x09: case 0x0a: case 0x0c: case 0x0d: + case 0x20: + /* Ignore whitespace */ + continue; + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/ + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/ + clv = (clv << 4) + (ch - 0x30); + break; + case 0x41: case 0x42: case 0x43: /* ABC */ + case 0x44: case 0x45: case 0x46: /* DEF */ + clv = (clv << 4) + (ch - 0x41 + 10); + break; + case 0x61: case 0x62: case 0x63: /* abc */ + case 0x64: case 0x65: case 0x66: /* def */ + clv = (clv << 4) + (ch - 0x61 + 10); + break; + default: + *buf = 0; /* JIC */ + return -1; + } + if(half++) { + half = 0; + *buf++ = clv; + chunk_stop = p + 1; + } + } + + /* + * Check partial decoding. + */ + if(half) { + if(have_more) { + /* + * Partial specification is fine, + * because no more more PXER_TEXT data is available. + */ + *buf++ = clv << 4; + chunk_stop = p; + } + } else { + chunk_stop = p; + } + + st->size = buf - st->buf; /* Adjust the buffer size */ + assert(st->size <= _ns); + st->buf[st->size] = 0; /* Courtesy termination */ + + return (chunk_stop - (const char *)chunk_buf); /* Converted size */ +} + +/* + * Convert from binary format: "00101011101" + */ +static ssize_t OCTET_STRING__convert_binary(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) { + BIT_STRING_t *st = (BIT_STRING_t *)sptr; + const char *p = (const char *)chunk_buf; + const char *pend = p + chunk_size; + int bits_unused = st->bits_unused & 0x7; + uint8_t *buf; + + /* Reallocate buffer according to high cap estimation */ + ssize_t _ns = st->size + (chunk_size + 7) / 8; + void *nptr = REALLOC(st->buf, _ns + 1); + if(!nptr) return -1; + st->buf = (uint8_t *)nptr; + buf = st->buf + st->size; + + (void)have_more; + + if(bits_unused == 0) + bits_unused = 8; + else if(st->size) + buf--; + + /* + * Convert series of 0 and 1 into the octet string. + */ + for(; p < pend; p++) { + int ch = *(const unsigned char *)p; + switch(ch) { + case 0x09: case 0x0a: case 0x0c: case 0x0d: + case 0x20: + /* Ignore whitespace */ + break; + case 0x30: + case 0x31: + if(bits_unused-- <= 0) { + *++buf = 0; /* Clean the cell */ + bits_unused = 7; + } + *buf |= (ch&1) << bits_unused; + break; + default: + st->bits_unused = bits_unused; + return -1; + } + } + + if(bits_unused == 8) { + st->size = buf - st->buf; + st->bits_unused = 0; + } else { + st->size = buf - st->buf + 1; + st->bits_unused = bits_unused; + } + + assert(st->size <= _ns); + st->buf[st->size] = 0; /* Courtesy termination */ + + return chunk_size; /* Converted in full */ +} + +/* + * Something like strtod(), but with stricter rules. + */ +static int +OS__strtoent(int base, const char *buf, const char *end, int32_t *ret_value) { + int32_t val = 0; + const char *p; + + for(p = buf; p < end; p++) { + int ch = *p; + + /* Strange huge value */ + if((val * base + base) < 0) + return -1; + + switch(ch) { + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: /*01234*/ + case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: /*56789*/ + val = val * base + (ch - 0x30); + break; + case 0x41: case 0x42: case 0x43: /* ABC */ + case 0x44: case 0x45: case 0x46: /* DEF */ + val = val * base + (ch - 0x41 + 10); + break; + case 0x61: case 0x62: case 0x63: /* abc */ + case 0x64: case 0x65: case 0x66: /* def */ + val = val * base + (ch - 0x61 + 10); + break; + case 0x3b: /* ';' */ + *ret_value = val; + return (p - buf) + 1; + default: + return -1; /* Character set error */ + } + } + + *ret_value = -1; + return (p - buf); +} + +/* + * Convert from the plain UTF-8 format, expanding entity references: "2 < 3" + */ +static ssize_t OCTET_STRING__convert_entrefs(void *sptr, const void *chunk_buf, size_t chunk_size, int have_more) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; + const char *p = (const char *)chunk_buf; + const char *pend = p + chunk_size; + uint8_t *buf; + + /* Reallocate buffer */ + ssize_t _ns = st->size + chunk_size; + void *nptr = REALLOC(st->buf, _ns + 1); + if(!nptr) return -1; + st->buf = (uint8_t *)nptr; + buf = st->buf + st->size; + + /* + * Convert series of 0 and 1 into the octet string. + */ + for(; p < pend; p++) { + int ch = *(const unsigned char *)p; + int len; /* Length of the rest of the chunk */ + + if(ch != 0x26 /* '&' */) { + *buf++ = ch; + continue; /* That was easy... */ + } + + /* + * Process entity reference. + */ + len = chunk_size - (p - (const char *)chunk_buf); + if(len == 1 /* "&" */) goto want_more; + if(p[1] == 0x23 /* '#' */) { + const char *pval; /* Pointer to start of digits */ + int32_t val = 0; /* Entity reference value */ + int base; + + if(len == 2 /* "&#" */) goto want_more; + if(p[2] == 0x78 /* 'x' */) + pval = p + 3, base = 16; + else + pval = p + 2, base = 10; + len = OS__strtoent(base, pval, p + len, &val); + if(len == -1) { + /* Invalid charset. Just copy verbatim. */ + *buf++ = ch; + continue; + } + if(!len || pval[len-1] != 0x3b) goto want_more; + assert(val > 0); + p += (pval - p) + len - 1; /* Advance past entref */ + + if(val < 0x80) { + *buf++ = (char)val; + } else if(val < 0x800) { + *buf++ = 0xc0 | ((val >> 6)); + *buf++ = 0x80 | ((val & 0x3f)); + } else if(val < 0x10000) { + *buf++ = 0xe0 | ((val >> 12)); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } else if(val < 0x200000) { + *buf++ = 0xf0 | ((val >> 18)); + *buf++ = 0x80 | ((val >> 12) & 0x3f); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } else if(val < 0x4000000) { + *buf++ = 0xf8 | ((val >> 24)); + *buf++ = 0x80 | ((val >> 18) & 0x3f); + *buf++ = 0x80 | ((val >> 12) & 0x3f); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } else { + *buf++ = 0xfc | ((val >> 30) & 0x1); + *buf++ = 0x80 | ((val >> 24) & 0x3f); + *buf++ = 0x80 | ((val >> 18) & 0x3f); + *buf++ = 0x80 | ((val >> 12) & 0x3f); + *buf++ = 0x80 | ((val >> 6) & 0x3f); + *buf++ = 0x80 | ((val & 0x3f)); + } + } else { + /* + * Ugly, limited parsing of & > < + */ + char *sc = (char *)memchr(p, 0x3b, len > 5 ? 5 : len); + if(!sc) goto want_more; + if((sc - p) == 4 + && p[1] == 0x61 /* 'a' */ + && p[2] == 0x6d /* 'm' */ + && p[3] == 0x70 /* 'p' */) { + *buf++ = 0x26; + p = sc; + continue; + } + if((sc - p) == 3) { + if(p[1] == 0x6c) { + *buf = 0x3c; /* '<' */ + } else if(p[1] == 0x67) { + *buf = 0x3e; /* '>' */ + } else { + /* Unsupported entity reference */ + *buf++ = ch; + continue; + } + if(p[2] != 0x74) { + /* Unsupported entity reference */ + *buf++ = ch; + continue; + } + buf++; + p = sc; + continue; + } + /* Unsupported entity reference */ + *buf++ = ch; + } + + continue; + want_more: + if(have_more) { + /* + * We know that no more data (of the same type) + * is coming. Copy the rest verbatim. + */ + *buf++ = ch; + continue; + } + chunk_size = (p - (const char *)chunk_buf); + /* Processing stalled: need more data */ + break; + } + + st->size = buf - st->buf; + assert(st->size <= _ns); + st->buf[st->size] = 0; /* Courtesy termination */ + + return chunk_size; /* Converted in full */ +} + +/* + * Decode OCTET STRING from the XML element's body. + */ +static asn_dec_rval_t +OCTET_STRING__decode_xer(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size, + int (*opt_unexpected_tag_decoder) + (void *struct_ptr, const void *chunk_buf, size_t chunk_size), + ssize_t (*body_receiver) + (void *struct_ptr, const void *chunk_buf, size_t chunk_size, + int have_more) +) { + OCTET_STRING_t *st = (OCTET_STRING_t *)*sptr; + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + asn_struct_ctx_t *ctx; /* Per-structure parser context */ + asn_dec_rval_t rval; /* Return value from the decoder */ + int st_allocated; + + /* + * Create the string if does not exist. + */ + if(!st) { + st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size); + *sptr = (void *)st; + if(!st) goto sta_failed; + st_allocated = 1; + } else { + st_allocated = 0; + } + if(!st->buf) { + /* This is separate from above section */ + st->buf = (uint8_t *)CALLOC(1, 1); + if(!st->buf) { + if(st_allocated) { + *sptr = 0; + goto stb_failed; + } else { + goto sta_failed; + } + } + } + + /* Restore parsing context */ + ctx = (asn_struct_ctx_t *)(((char *)*sptr) + specs->ctx_offset); + + return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag, + buf_ptr, size, opt_unexpected_tag_decoder, body_receiver); + +stb_failed: + FREEMEM(st); +sta_failed: + rval.code = RC_FAIL; + rval.consumed = 0; + return rval; +} + +/* + * Decode OCTET STRING from the hexadecimal data. + */ +asn_dec_rval_t +OCTET_STRING_decode_xer_hex(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size) { + return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname, + buf_ptr, size, 0, OCTET_STRING__convert_hexadecimal); +} + +/* + * Decode OCTET STRING from the binary (0/1) data. + */ +asn_dec_rval_t +OCTET_STRING_decode_xer_binary(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size) { + return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname, + buf_ptr, size, 0, OCTET_STRING__convert_binary); +} + +/* + * Decode OCTET STRING from the string (ASCII/UTF-8) data. + */ +asn_dec_rval_t +OCTET_STRING_decode_xer_utf8(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, void **sptr, + const char *opt_mname, const void *buf_ptr, size_t size) { + return OCTET_STRING__decode_xer(opt_codec_ctx, td, sptr, opt_mname, + buf_ptr, size, + OCTET_STRING__handle_control_chars, + OCTET_STRING__convert_entrefs); +} + +asn_dec_rval_t +OCTET_STRING_decode_uper(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_per_constraints_t *constraints, + void **sptr, asn_per_data_t *pd) { + + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + asn_per_constraint_t *ct = constraints ? &constraints->size + : (td->per_constraints + ? &td->per_constraints->size + : &asn_DEF_OCTET_STRING_constraint); + asn_dec_rval_t rval = { RC_OK, 0 }; + BIT_STRING_t *st = (BIT_STRING_t *)*sptr; + ssize_t consumed_myself = 0; + int repeat; + int unit_bits = (specs->subvariant != 1) * 7 + 1; + + (void)opt_codec_ctx; + + /* + * Allocate the string. + */ + if(!st) { + st = (BIT_STRING_t *)(*sptr = CALLOC(1, specs->struct_size)); + if(!st) RETURN(RC_FAIL); + } + + ASN_DEBUG("PER Decoding %s %ld .. %ld bits %d", + ct->flags & APC_EXTENSIBLE ? "extensible" : "fixed", + ct->lower_bound, ct->upper_bound, ct->effective_bits); + + if(ct->flags & APC_EXTENSIBLE) { + int inext = per_get_few_bits(pd, 1); + if(inext < 0) RETURN(RC_WMORE); + if(inext) ct = &asn_DEF_OCTET_STRING_constraint; + consumed_myself = 0; + } + + if(ct->effective_bits >= 0 + && (!st->buf || st->size < ct->upper_bound)) { + FREEMEM(st->buf); + if(unit_bits == 1) { + st->size = (ct->upper_bound + 7) >> 3; + } else { + st->size = ct->upper_bound; + } + st->buf = (uint8_t *)MALLOC(st->size + 1); + if(!st->buf) { st->size = 0; RETURN(RC_FAIL); } + } + + /* X.691, #16.5: zero-length encoding */ + /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ + /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ + if(ct->effective_bits == 0) { + int ret = per_get_many_bits(pd, st->buf, 0, + unit_bits * ct->upper_bound); + if(ret < 0) RETURN(RC_WMORE); + consumed_myself += unit_bits * ct->upper_bound; + st->buf[st->size] = 0; + if(unit_bits == 1 && (ct->upper_bound & 0x7)) + st->bits_unused = 8 - (ct->upper_bound & 0x7); + RETURN(RC_OK); + } + + st->size = 0; + do { + ssize_t len_bytes; + ssize_t len_bits; + void *p; + int ret; + + /* Get the PER length */ + len_bits = uper_get_length(pd, ct->effective_bits, &repeat); + if(len_bits < 0) RETURN(RC_WMORE); + len_bits += ct->lower_bound; + + ASN_DEBUG("Got PER length eb %ld, len %ld, %s (%s)", + (long)ct->effective_bits, (long)len_bits, + repeat ? "repeat" : "once", td->name); + if(unit_bits == 1) { + len_bytes = (len_bits + 7) >> 3; + if(len_bits & 0x7) + st->bits_unused = 8 - (len_bits & 0x7); + /* len_bits be multiple of 16K if repeat is set */ + } else { + len_bytes = len_bits; + len_bits = len_bytes << 3; + } + p = REALLOC(st->buf, st->size + len_bytes + 1); + if(!p) RETURN(RC_FAIL); + st->buf = (uint8_t *)p; + + ret = per_get_many_bits(pd, &st->buf[st->size], 0, len_bits); + if(ret < 0) RETURN(RC_WMORE); + st->size += len_bytes; + } while(repeat); + st->buf[st->size] = 0; /* nul-terminate */ + + return rval; +} + +asn_enc_rval_t +OCTET_STRING_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + asn_per_constraint_t *ct = constraints ? &constraints->size + : (td->per_constraints + ? &td->per_constraints->size + : &asn_DEF_OCTET_STRING_constraint); + const BIT_STRING_t *st = (const BIT_STRING_t *)sptr; + int unit_bits = (specs->subvariant != 1) * 7 + 1; + asn_enc_rval_t er; + int ct_extensible = ct->flags & APC_EXTENSIBLE; + int inext = 0; /* Lies not within extension root */ + int sizeinunits = 0; + const uint8_t *buf; + int ret; + + if(!st || !st->buf) + _ASN_ENCODE_FAILED; + sizeinunits = st->size; + + if(unit_bits == 1) { + ASN_DEBUG("BIT STRING of %d bytes, %d bits unused", + sizeinunits, st->bits_unused); + sizeinunits = sizeinunits * 8 - (st->bits_unused & 0x07); + } + + ASN_DEBUG("Encoding %s into %d units of %d bits" + " (%d..%d, effective %d)%s", + td->name, sizeinunits, unit_bits, + ct->lower_bound, ct->upper_bound, + ct->effective_bits, ct_extensible ? " EXT" : ""); + + /* Figure out wheter size lies within PER visible consrtaint */ + + if(ct->effective_bits >= 0) { + if(sizeinunits < ct->lower_bound + || sizeinunits > ct->upper_bound) { + if(ct_extensible) { + ct = &asn_DEF_OCTET_STRING_constraint; + inext = 1; + } else + _ASN_ENCODE_FAILED; + } + } else { + inext = 0; + } + + if(ct_extensible) { + /* Declare whether length is [not] within extension root */ + if(per_put_few_bits(po, inext, 1)) + _ASN_ENCODE_FAILED; + } + + /* X.691, #16.5: zero-length encoding */ + /* X.691, #16.6: short fixed length encoding (up to 2 octets) */ + /* X.691, #16.7: long fixed length encoding (up to 64K octets) */ + if(ct->effective_bits >= 0) { + ASN_DEBUG("Encoding %d bytes (%ld), length in %d bits", + st->size, sizeinunits - ct->lower_bound, + ct->effective_bits); + ret = per_put_few_bits(po, sizeinunits - ct->lower_bound, + ct->effective_bits); + if(ret) _ASN_ENCODE_FAILED; + ret = per_put_many_bits(po, st->buf, sizeinunits * unit_bits); + if(ret) _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + ASN_DEBUG("Encoding %d bytes", st->size); + + if(sizeinunits == 0) { + if(uper_put_length(po, 0)) + _ASN_ENCODE_FAILED; + _ASN_ENCODED_OK(er); + } + + buf = st->buf; + while(sizeinunits) { + ssize_t maySave = uper_put_length(po, sizeinunits); + if(maySave < 0) _ASN_ENCODE_FAILED; + + ASN_DEBUG("Encoding %d of %d", maySave, sizeinunits); + + ret = per_put_many_bits(po, buf, maySave * unit_bits); + if(ret) _ASN_ENCODE_FAILED; + + if(unit_bits == 1) + buf += maySave >> 3; + else + buf += maySave; + sizeinunits -= maySave; + assert(!(maySave & 0x07) || !sizeinunits); + } + + _ASN_ENCODED_OK(er); +} + +int +OCTET_STRING_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + static const char *h2c = "0123456789ABCDEF"; + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + char scratch[16 * 3 + 4]; + char *p = scratch; + uint8_t *buf; + uint8_t *end; + size_t i; + + (void)td; /* Unused argument */ + + if(!st || !st->buf) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* + * Dump the contents of the buffer in hexadecimal. + */ + buf = st->buf; + end = buf + st->size; + for(i = 0; buf < end; buf++, i++) { + if(!(i % 16) && (i || st->size > 16)) { + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + _i_INDENT(1); + p = scratch; + } + *p++ = h2c[(*buf >> 4) & 0x0F]; + *p++ = h2c[*buf & 0x0F]; + *p++ = 0x20; + } + + if(p > scratch) { + p--; /* Remove the tail space */ + if(cb(scratch, p - scratch, app_key) < 0) + return -1; + } + + return 0; +} + +int +OCTET_STRING_print_utf8(asn_TYPE_descriptor_t *td, const void *sptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + const OCTET_STRING_t *st = (const OCTET_STRING_t *)sptr; + + (void)td; /* Unused argument */ + (void)ilevel; /* Unused argument */ + + if(st && st->buf) { + return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0; + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +void +OCTET_STRING_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { + OCTET_STRING_t *st = (OCTET_STRING_t *)sptr; + asn_OCTET_STRING_specifics_t *specs = td && td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + asn_struct_ctx_t *ctx = (asn_struct_ctx_t *) + ((char *)st + specs->ctx_offset); + struct _stack *stck; + + if(!td || !st) + return; + + ASN_DEBUG("Freeing %s as OCTET STRING", td->name); + + if(st->buf) { + FREEMEM(st->buf); + } + + /* + * Remove decode-time stack. + */ + stck = (struct _stack *)ctx->ptr; + if(stck) { + while(stck->tail) { + struct _stack_el *sel = stck->tail; + stck->tail = sel->prev; + FREEMEM(sel); + } + FREEMEM(stck); + } + + if(!contents_only) { + FREEMEM(st); + } +} + +/* + * Conversion routines. + */ +int +OCTET_STRING_fromBuf(OCTET_STRING_t *st, const char *str, int len) { + void *buf; + + if(st == 0 || (str == 0 && len)) { + errno = EINVAL; + return -1; + } + + /* + * Clear the OCTET STRING. + */ + if(str == NULL) { + FREEMEM(st->buf); + st->buf = 0; + st->size = 0; + return 0; + } + + /* Determine the original string size, if not explicitly given */ + if(len < 0) + len = strlen(str); + + /* Allocate and fill the memory */ + buf = MALLOC(len + 1); + if(buf == NULL) + return -1; + + memcpy(buf, str, len); + ((uint8_t *)buf)[len] = '\0'; /* Couldn't use memcpy(len+1)! */ + FREEMEM(st->buf); + st->buf = (uint8_t *)buf; + st->size = len; + + return 0; +} + +OCTET_STRING_t * +OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, const char *str, int len) { + asn_OCTET_STRING_specifics_t *specs = td->specifics + ? (asn_OCTET_STRING_specifics_t *)td->specifics + : &asn_DEF_OCTET_STRING_specs; + OCTET_STRING_t *st; + + st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size); + if(st && str && OCTET_STRING_fromBuf(st, str, len)) { + FREEMEM(st); + st = NULL; + } + + return st; +} + diff --git a/libs/smux/ObjectName.c b/libs/smux/ObjectName.c new file mode 100644 index 00000000..d10f7193 --- /dev/null +++ b/libs/smux/ObjectName.c @@ -0,0 +1,110 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "ObjectName.h" + +int +ObjectName_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_OBJECT_IDENTIFIER.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using OBJECT_IDENTIFIER, + * so here we adjust the DEF accordingly. + */ +static void +ObjectName_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_OBJECT_IDENTIFIER.free_struct; + td->print_struct = asn_DEF_OBJECT_IDENTIFIER.print_struct; + td->ber_decoder = asn_DEF_OBJECT_IDENTIFIER.ber_decoder; + td->der_encoder = asn_DEF_OBJECT_IDENTIFIER.der_encoder; + td->xer_decoder = asn_DEF_OBJECT_IDENTIFIER.xer_decoder; + td->xer_encoder = asn_DEF_OBJECT_IDENTIFIER.xer_encoder; + td->uper_decoder = asn_DEF_OBJECT_IDENTIFIER.uper_decoder; + td->uper_encoder = asn_DEF_OBJECT_IDENTIFIER.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_OBJECT_IDENTIFIER.per_constraints; + td->elements = asn_DEF_OBJECT_IDENTIFIER.elements; + td->elements_count = asn_DEF_OBJECT_IDENTIFIER.elements_count; + td->specifics = asn_DEF_OBJECT_IDENTIFIER.specifics; +} + +void +ObjectName_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + ObjectName_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +ObjectName_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + ObjectName_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +ObjectName_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + ObjectName_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +ObjectName_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + ObjectName_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +ObjectName_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + ObjectName_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +ObjectName_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + ObjectName_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_ObjectName_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_ObjectName = { + "ObjectName", + "ObjectName", + ObjectName_free, + ObjectName_print, + ObjectName_constraint, + ObjectName_decode_ber, + ObjectName_encode_der, + ObjectName_decode_xer, + ObjectName_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_ObjectName_tags_1, + sizeof(asn_DEF_ObjectName_tags_1) + /sizeof(asn_DEF_ObjectName_tags_1[0]), /* 1 */ + asn_DEF_ObjectName_tags_1, /* Same as above */ + sizeof(asn_DEF_ObjectName_tags_1) + /sizeof(asn_DEF_ObjectName_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/ObjectSyntax.c b/libs/smux/ObjectSyntax.c new file mode 100644 index 00000000..b0542d90 --- /dev/null +++ b/libs/smux/ObjectSyntax.c @@ -0,0 +1,74 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "ObjectSyntax.h" + +static asn_TYPE_member_t asn_MBR_ObjectSyntax_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct ObjectSyntax, choice.simple), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_SimpleSyntax, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "simple" + }, + { ATF_NOFLAGS, 0, offsetof(struct ObjectSyntax, choice.application_wide), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ApplicationSyntax, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "application-wide" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_ObjectSyntax_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* number at 73 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 0, 0, 0 }, /* string at 76 */ + { (ASN_TAG_CLASS_UNIVERSAL | (5 << 2)), 0, 0, 0 }, /* empty at 82 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* object at 79 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 1, 0, 0 }, /* internet at 113 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 1, 0, 0 }, /* counter at 91 */ + { (ASN_TAG_CLASS_APPLICATION | (2 << 2)), 1, 0, 0 }, /* gauge at 94 */ + { (ASN_TAG_CLASS_APPLICATION | (3 << 2)), 1, 0, 0 }, /* ticks at 97 */ + { (ASN_TAG_CLASS_APPLICATION | (4 << 2)), 1, 0, 0 } /* arbitrary at 104 */ +}; +static asn_CHOICE_specifics_t asn_SPC_ObjectSyntax_specs_1 = { + sizeof(struct ObjectSyntax), + offsetof(struct ObjectSyntax, _asn_ctx), + offsetof(struct ObjectSyntax, present), + sizeof(((struct ObjectSyntax *)0)->present), + asn_MAP_ObjectSyntax_tag2el_1, + 9, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +asn_TYPE_descriptor_t asn_DEF_ObjectSyntax = { + "ObjectSyntax", + "ObjectSyntax", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + 0, /* No PER visible constraints */ + asn_MBR_ObjectSyntax_1, + 2, /* Elements count */ + &asn_SPC_ObjectSyntax_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/Opaque.c b/libs/smux/Opaque.c new file mode 100644 index 00000000..bccff85d --- /dev/null +++ b/libs/smux/Opaque.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "Opaque.h" + +int +Opaque_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_OCTET_STRING.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using OCTET_STRING, + * so here we adjust the DEF accordingly. + */ +static void +Opaque_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_OCTET_STRING.free_struct; + td->print_struct = asn_DEF_OCTET_STRING.print_struct; + td->ber_decoder = asn_DEF_OCTET_STRING.ber_decoder; + td->der_encoder = asn_DEF_OCTET_STRING.der_encoder; + td->xer_decoder = asn_DEF_OCTET_STRING.xer_decoder; + td->xer_encoder = asn_DEF_OCTET_STRING.xer_encoder; + td->uper_decoder = asn_DEF_OCTET_STRING.uper_decoder; + td->uper_encoder = asn_DEF_OCTET_STRING.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_OCTET_STRING.per_constraints; + td->elements = asn_DEF_OCTET_STRING.elements; + td->elements_count = asn_DEF_OCTET_STRING.elements_count; + td->specifics = asn_DEF_OCTET_STRING.specifics; +} + +void +Opaque_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + Opaque_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +Opaque_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + Opaque_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +Opaque_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + Opaque_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +Opaque_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + Opaque_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +Opaque_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + Opaque_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +Opaque_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + Opaque_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_Opaque_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (4 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_Opaque = { + "Opaque", + "Opaque", + Opaque_free, + Opaque_print, + Opaque_constraint, + Opaque_decode_ber, + Opaque_encode_der, + Opaque_decode_xer, + Opaque_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_Opaque_tags_1, + sizeof(asn_DEF_Opaque_tags_1) + /sizeof(asn_DEF_Opaque_tags_1[0]) - 1, /* 1 */ + asn_DEF_Opaque_tags_1, /* Same as above */ + sizeof(asn_DEF_Opaque_tags_1) + /sizeof(asn_DEF_Opaque_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/OpenPDU.c b/libs/smux/OpenPDU.c new file mode 100644 index 00000000..a841714e --- /dev/null +++ b/libs/smux/OpenPDU.c @@ -0,0 +1,57 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "OpenPDU.h" + +static asn_TYPE_member_t asn_MBR_OpenPDU_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct OpenPDU, choice.simple), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_SimpleOpen, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "simple" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_OpenPDU_tag2el_1[] = { + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 0, 0, 0 } /* simple at 52 */ +}; +static asn_CHOICE_specifics_t asn_SPC_OpenPDU_specs_1 = { + sizeof(struct OpenPDU), + offsetof(struct OpenPDU, _asn_ctx), + offsetof(struct OpenPDU, present), + sizeof(((struct OpenPDU *)0)->present), + asn_MAP_OpenPDU_tag2el_1, + 1, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +asn_TYPE_descriptor_t asn_DEF_OpenPDU = { + "OpenPDU", + "OpenPDU", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + 0, /* No PER visible constraints */ + asn_MBR_OpenPDU_1, + 1, /* Elements count */ + &asn_SPC_OpenPDU_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/PDU.c b/libs/smux/PDU.c new file mode 100644 index 00000000..0087d19f --- /dev/null +++ b/libs/smux/PDU.c @@ -0,0 +1,91 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "PDU.h" + +static asn_TYPE_member_t asn_MBR_PDU_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct PDU, request_id), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "request-id" + }, + { ATF_NOFLAGS, 0, offsetof(struct PDU, error_status), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "error-status" + }, + { ATF_NOFLAGS, 0, offsetof(struct PDU, error_index), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "error-index" + }, + { ATF_NOFLAGS, 0, offsetof(struct PDU, variable_bindings), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_VarBindList, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "variable-bindings" + }, +}; +static ber_tlv_tag_t asn_DEF_PDU_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_PDU_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 2 }, /* request-id at 73 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 1, -1, 1 }, /* error-status at 77 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, -2, 0 }, /* error-index at 86 */ + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 3, 0, 0 } /* variable-bindings at 90 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_PDU_specs_1 = { + sizeof(struct PDU), + offsetof(struct PDU, _asn_ctx), + asn_MAP_PDU_tag2el_1, + 4, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_PDU = { + "PDU", + "PDU", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_PDU_tags_1, + sizeof(asn_DEF_PDU_tags_1) + /sizeof(asn_DEF_PDU_tags_1[0]), /* 1 */ + asn_DEF_PDU_tags_1, /* Same as above */ + sizeof(asn_DEF_PDU_tags_1) + /sizeof(asn_DEF_PDU_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_PDU_1, + 4, /* Elements count */ + &asn_SPC_PDU_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/PDUs.c b/libs/smux/PDUs.c new file mode 100644 index 00000000..162530c0 --- /dev/null +++ b/libs/smux/PDUs.c @@ -0,0 +1,97 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "PDUs.h" + +static asn_TYPE_member_t asn_MBR_PDUs_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct PDUs, choice.get_request), + (ASN_TAG_CLASS_CONTEXT | (0 << 2)), + 0, + &asn_DEF_GetRequest_PDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "get-request" + }, + { ATF_NOFLAGS, 0, offsetof(struct PDUs, choice.get_next_request), + (ASN_TAG_CLASS_CONTEXT | (1 << 2)), + 0, + &asn_DEF_GetNextRequest_PDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "get-next-request" + }, + { ATF_NOFLAGS, 0, offsetof(struct PDUs, choice.get_response), + (ASN_TAG_CLASS_CONTEXT | (2 << 2)), + 0, + &asn_DEF_GetResponse_PDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "get-response" + }, + { ATF_NOFLAGS, 0, offsetof(struct PDUs, choice.set_request), + (ASN_TAG_CLASS_CONTEXT | (3 << 2)), + 0, + &asn_DEF_SetRequest_PDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "set-request" + }, + { ATF_NOFLAGS, 0, offsetof(struct PDUs, choice.trap), + (ASN_TAG_CLASS_CONTEXT | (4 << 2)), + 0, + &asn_DEF_Trap_PDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "trap" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_PDUs_tag2el_1[] = { + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* get-request at 34 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* get-next-request at 37 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* get-response at 40 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 }, /* set-request at 43 */ + { (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 4, 0, 0 } /* trap at 47 */ +}; +static asn_CHOICE_specifics_t asn_SPC_PDUs_specs_1 = { + sizeof(struct PDUs), + offsetof(struct PDUs, _asn_ctx), + offsetof(struct PDUs, present), + sizeof(((struct PDUs *)0)->present), + asn_MAP_PDUs_tag2el_1, + 5, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +asn_TYPE_descriptor_t asn_DEF_PDUs = { + "PDUs", + "PDUs", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + 0, /* No PER visible constraints */ + asn_MBR_PDUs_1, + 5, /* Elements count */ + &asn_SPC_PDUs_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/PhysAddress.c b/libs/smux/PhysAddress.c new file mode 100644 index 00000000..eed47386 --- /dev/null +++ b/libs/smux/PhysAddress.c @@ -0,0 +1,110 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "PhysAddress.h" + +int +PhysAddress_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_OCTET_STRING.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using OCTET_STRING, + * so here we adjust the DEF accordingly. + */ +static void +PhysAddress_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_OCTET_STRING.free_struct; + td->print_struct = asn_DEF_OCTET_STRING.print_struct; + td->ber_decoder = asn_DEF_OCTET_STRING.ber_decoder; + td->der_encoder = asn_DEF_OCTET_STRING.der_encoder; + td->xer_decoder = asn_DEF_OCTET_STRING.xer_decoder; + td->xer_encoder = asn_DEF_OCTET_STRING.xer_encoder; + td->uper_decoder = asn_DEF_OCTET_STRING.uper_decoder; + td->uper_encoder = asn_DEF_OCTET_STRING.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_OCTET_STRING.per_constraints; + td->elements = asn_DEF_OCTET_STRING.elements; + td->elements_count = asn_DEF_OCTET_STRING.elements_count; + td->specifics = asn_DEF_OCTET_STRING.specifics; +} + +void +PhysAddress_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + PhysAddress_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +PhysAddress_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + PhysAddress_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +PhysAddress_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + PhysAddress_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +PhysAddress_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + PhysAddress_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +PhysAddress_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + PhysAddress_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +PhysAddress_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + PhysAddress_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_PhysAddress_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_PhysAddress = { + "PhysAddress", + "PhysAddress", + PhysAddress_free, + PhysAddress_print, + PhysAddress_constraint, + PhysAddress_decode_ber, + PhysAddress_encode_der, + PhysAddress_decode_xer, + PhysAddress_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_PhysAddress_tags_1, + sizeof(asn_DEF_PhysAddress_tags_1) + /sizeof(asn_DEF_PhysAddress_tags_1[0]), /* 1 */ + asn_DEF_PhysAddress_tags_1, /* Same as above */ + sizeof(asn_DEF_PhysAddress_tags_1) + /sizeof(asn_DEF_PhysAddress_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/RFC1155-SMI.asn1 b/libs/smux/RFC1155-SMI.asn1 new file mode 100644 index 00000000..132e3408 --- /dev/null +++ b/libs/smux/RFC1155-SMI.asn1 @@ -0,0 +1,135 @@ + +-- WinAgents MIB Extraction Wizard +-- Extracted from rfc1155.txt 17.03.2005 16:16:50 + +RFC1155-SMI DEFINITIONS ::= BEGIN + +--EXPORTS EVERYTHING +-- internet, directory, mgmt, +-- experimental, private, enterprises, +-- OBJECT-TYPE, ObjectName, ObjectSyntax, SimpleSyntax, +-- ApplicationSyntax, NetworkAddress, IpAddress, +-- Counter, Gauge, TimeTicks, Opaque; + + -- the path to the root + + internet OBJECT IDENTIFIER ::= { iso org(3) dod(6) 1 } + + directory OBJECT IDENTIFIER ::= { internet 1 } + + mgmt OBJECT IDENTIFIER ::= { internet 2 } + + experimental OBJECT IDENTIFIER ::= { internet 3 } + + private OBJECT IDENTIFIER ::= { internet 4 } + enterprises OBJECT IDENTIFIER ::= { private 1 } + + + -- definition of object types + +-- MIB Extraction: All MACRO definitions are predefined by compiler +-- commented by MIB Extraction: OBJECT-TYPE MACRO ::= +-- commented by MIB Extraction: BEGIN +-- commented by MIB Extraction: TYPE NOTATION ::= "SYNTAX" type (TYPE ObjectSyntax) +-- commented by MIB Extraction: "ACCESS" Access +-- commented by MIB Extraction: "STATUS" Status +-- commented by MIB Extraction: VALUE NOTATION ::= value (VALUE ObjectName) +-- commented by MIB Extraction: +-- commented by MIB Extraction: Access ::= "read-only" +-- commented by MIB Extraction: | "read-write" +-- commented by MIB Extraction: | "write-only" +-- commented by MIB Extraction: | "not-accessible" +-- commented by MIB Extraction: Status ::= "mandatory" +-- commented by MIB Extraction: | "optional" +-- commented by MIB Extraction: | "obsolete" +-- commented by MIB Extraction: END + + -- names of objects in the MIB + + ObjectName ::= + OBJECT IDENTIFIER + + + -- syntax of objects in the MIB + + ObjectSyntax ::= + CHOICE { + simple + SimpleSyntax, + + -- note that simple SEQUENCEs are not directly + -- mentioned here to keep things simple (i.e., + -- prevent mis-use). However, application-wide + -- types which are IMPLICITly encoded simple + -- SEQUENCEs may appear in the following CHOICE + + application-wide + ApplicationSyntax + } + + SimpleSyntax ::= + CHOICE { + number + INTEGER, + + string + OCTET STRING, + + object + OBJECT IDENTIFIER, + + empty + NULL + } + + ApplicationSyntax ::= + CHOICE { + address + NetworkAddress, + + counter + Counter, + + gauge + Gauge, + + ticks + TimeTicks, + + arbitrary + Opaque + + -- other application-wide types, as they are + -- defined, will be added here + } + + + -- application-wide types + + NetworkAddress ::= + CHOICE { + internet + IpAddress + } + + IpAddress ::= + [APPLICATION 0] -- in network-byte order + IMPLICIT OCTET STRING (SIZE (4)) + + Counter ::= + [APPLICATION 1] + IMPLICIT INTEGER (0..4294967295) + + Gauge ::= + [APPLICATION 2] + IMPLICIT INTEGER (0..4294967295) + + TimeTicks ::= + [APPLICATION 3] + IMPLICIT INTEGER (0..4294967295) + + Opaque ::= + [APPLICATION 4] -- arbitrary ASN.1 value, + IMPLICIT OCTET STRING -- "double-wrapped" + + END diff --git a/libs/smux/RFC1157-SNMP.asn1 b/libs/smux/RFC1157-SNMP.asn1 new file mode 100644 index 00000000..166f7e78 --- /dev/null +++ b/libs/smux/RFC1157-SNMP.asn1 @@ -0,0 +1,143 @@ + +-- WinAgents MIB Extraction Wizard +-- Extracted from rfc1157.txt 16.03.2005 20:20:14 + +RFC1157-SNMP DEFINITIONS ::= BEGIN + + IMPORTS + ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks + FROM RFC1155-SMI; + + + -- top-level message + + Message ::= + SEQUENCE { + version -- version-1 for this RFC + INTEGER { + version-1(0) + }, + + community -- community name + OCTET STRING, + + data -- e.g., PDUs if trivial + ANY -- authentication is being used + } + + + -- protocol data units + + PDUs ::= + CHOICE { + get-request + GetRequest-PDU, + + get-next-request + GetNextRequest-PDU, + + get-response + GetResponse-PDU, + + set-request + SetRequest-PDU, + + trap + Trap-PDU + } + + + + + -- PDUs + + GetRequest-PDU ::= + [0] + IMPLICIT PDU + + GetNextRequest-PDU ::= + [1] + IMPLICIT PDU + + GetResponse-PDU ::= + [2] + IMPLICIT PDU + + SetRequest-PDU ::= + [3] + IMPLICIT PDU + + PDU ::= + SEQUENCE { + request-id + INTEGER, + + error-status -- sometimes ignored + INTEGER { + noError(0), + tooBig(1), + noSuchName(2), + badValue(3), + readOnly(4), + genErr(5) + }, + + error-index -- sometimes ignored + INTEGER, + + variable-bindings -- values are sometimes ignored + VarBindList + } + + Trap-PDU ::= + [4] + IMPLICIT SEQUENCE { + enterprise -- type of object generating + -- trap, see sysObjectID in [5] + + + OBJECT IDENTIFIER, + + agent-addr -- address of object generating + NetworkAddress, -- trap + + generic-trap -- generic trap type + INTEGER { + coldStart(0), + warmStart(1), + linkDown(2), + linkUp(3), + authenticationFailure(4), + egpNeighborLoss(5), + enterpriseSpecific(6) + }, + + specific-trap -- specific code, present even + INTEGER, -- if generic-trap is not + -- enterpriseSpecific + + time-stamp -- time elapsed between the last + TimeTicks, -- (re)initialization of the network + -- entity and the generation of the trap + + variable-bindings -- "interesting" information + VarBindList + } + + + -- variable bindings + + VarBind ::= + SEQUENCE { + name + ObjectName, + + value + ObjectSyntax + } + + VarBindList ::= + SEQUENCE OF + VarBind + + END \ No newline at end of file diff --git a/libs/smux/RFC1213-MIB.asn1 b/libs/smux/RFC1213-MIB.asn1 new file mode 100644 index 00000000..b9b1e857 --- /dev/null +++ b/libs/smux/RFC1213-MIB.asn1 @@ -0,0 +1,339 @@ + +-- WinAgents MIB Extraction Wizard +-- Extracted from rfc1213.txt 16.03.2005 20:20:14 + +RFC1213-MIB DEFINITIONS ::= BEGIN + +IMPORTS + mgmt, NetworkAddress, IpAddress, Counter, Gauge, + TimeTicks + FROM RFC1155-SMI + OBJECT-TYPE + FROM RFC-1212; + +-- This MIB module uses the extended OBJECT-TYPE macro as +-- defined in [14]; + + +-- MIB-II (same prefix as MIB-I) + +mib-2 OBJECT IDENTIFIER ::= { mgmt 1 } + +-- textual conventions + +DisplayString ::= + OCTET STRING +-- This data type is used to model textual information taken +-- from the NVT ASCII character set. By convention, objects +-- with this syntax are declared as having + +-- +-- SIZE (0..255) + +PhysAddress ::= + OCTET STRING +-- This data type is used to model media addresses. For many +-- types of media, this will be in a binary representation. +-- For example, an ethernet address would be represented as +-- a string of 6 octets. + + +-- groups in MIB-II + +system OBJECT IDENTIFIER ::= { mib-2 1 } + +interfaces OBJECT IDENTIFIER ::= { mib-2 2 } + +at OBJECT IDENTIFIER ::= { mib-2 3 } + +ip OBJECT IDENTIFIER ::= { mib-2 4 } + +icmp OBJECT IDENTIFIER ::= { mib-2 5 } + +tcp OBJECT IDENTIFIER ::= { mib-2 6 } + +udp OBJECT IDENTIFIER ::= { mib-2 7 } + +egp OBJECT IDENTIFIER ::= { mib-2 8 } + +-- historical (some say hysterical) +-- cmot OBJECT IDENTIFIER ::= { mib-2 9 } + +transmission OBJECT IDENTIFIER ::= { mib-2 10 } + +snmp OBJECT IDENTIFIER ::= { mib-2 11 } + + +-- the System group + +-- Implementation of the System group is mandatory for all +-- systems. If an agent is not configured to have a value +-- for any of these variables, a string of length 0 is +-- returned. + + +IfEntry ::= + SEQUENCE { + ifIndex + INTEGER, + + ifDescr + DisplayString, + ifType + INTEGER, + ifMtu + INTEGER, + ifSpeed + Gauge, + ifPhysAddress + PhysAddress, + ifAdminStatus + INTEGER, + ifOperStatus + INTEGER, + ifLastChange + TimeTicks, + ifInOctets + Counter, + ifInUcastPkts + Counter, + ifInNUcastPkts + Counter, + ifInDiscards + Counter, + ifInErrors + Counter, + ifInUnknownProtos + Counter, + ifOutOctets + Counter, + ifOutUcastPkts + Counter, + ifOutNUcastPkts + Counter, + ifOutDiscards + Counter, + ifOutErrors + Counter, + ifOutQLen + Gauge, + ifSpecific + OBJECT IDENTIFIER + } + + +-- the Address Translation group + +-- Implementation of the Address Translation group is +-- mandatory for all systems. Note however that this group +-- is deprecated by MIB-II. That is, it is being included + +-- solely for compatibility with MIB-I nodes, and will most +-- likely be excluded from MIB-III nodes. From MIB-II and +-- onwards, each network protocol group contains its own +-- address translation tables. + +-- The Address Translation group contains one table which is +-- the union across all interfaces of the translation tables +-- for converting a NetworkAddress (e.g., an IP address) into +-- a subnetwork-specific address. For lack of a better term, +-- this document refers to such a subnetwork-specific address +-- as a `physical' address. + +-- Examples of such translation tables are: for broadcast +-- media where ARP is in use, the translation table is +-- equivalent to the ARP cache; or, on an X.25 network where +-- non-algorithmic translation to X.121 addresses is +-- required, the translation table contains the +-- NetworkAddress to X.121 address equivalences. + + +AtEntry ::= + SEQUENCE { + atIfIndex + INTEGER, + + atPhysAddress + PhysAddress, + atNetAddress + NetworkAddress + } + + + + + +-- the IP address table + +-- The IP address table contains this entity's IP addressing +-- information. + + +IpAddrEntry ::= + SEQUENCE { + ipAdEntAddr + IpAddress, + ipAdEntIfIndex + INTEGER, + ipAdEntNetMask + IpAddress, + ipAdEntBcastAddr + INTEGER, + ipAdEntReasmMaxSize + INTEGER (0..65535) + } + + +IpRouteEntry ::= + SEQUENCE { + ipRouteDest + IpAddress, + ipRouteIfIndex + INTEGER, + ipRouteMetric1 + INTEGER, + ipRouteMetric2 + INTEGER, + ipRouteMetric3 + INTEGER, + ipRouteMetric4 + INTEGER, + ipRouteNextHop + IpAddress, + ipRouteType + INTEGER, + ipRouteProto + INTEGER, + ipRouteAge + INTEGER, + ipRouteMask + IpAddress, + ipRouteMetric5 + INTEGER, + + ipRouteInfo + OBJECT IDENTIFIER + } + + +IpNetToMediaEntry ::= + SEQUENCE { + ipNetToMediaIfIndex + INTEGER, + ipNetToMediaPhysAddress + PhysAddress, + ipNetToMediaNetAddress + IpAddress, + ipNetToMediaType + INTEGER + } + + + +TcpConnEntry ::= + SEQUENCE { + tcpConnState + INTEGER, + tcpConnLocalAddress + IpAddress, + tcpConnLocalPort + INTEGER (0..65535), + tcpConnRemAddress + IpAddress, + tcpConnRemPort + INTEGER (0..65535) + } + + +UdpEntry ::= + SEQUENCE { + udpLocalAddress + IpAddress, + udpLocalPort + INTEGER (0..65535) + } + + + +-- the EGP Neighbor table + +-- The EGP neighbor table contains information about this +-- entity's EGP neighbors. + + +EgpNeighEntry ::= + SEQUENCE { + egpNeighState + INTEGER, + egpNeighAddr + IpAddress, + egpNeighAs + INTEGER, + egpNeighInMsgs + Counter, + egpNeighInErrs + Counter, + egpNeighOutMsgs + Counter, + egpNeighOutErrs + Counter, + + egpNeighInErrMsgs + Counter, + egpNeighOutErrMsgs + Counter, + egpNeighStateUps + Counter, + egpNeighStateDowns + Counter, + egpNeighIntervalHello + INTEGER, + egpNeighIntervalPoll + INTEGER, + egpNeighMode + INTEGER, + egpNeighEventTrigger + INTEGER + } + + + +-- the Transmission group + +-- Based on the transmission media underlying each interface +-- on a system, the corresponding portion of the Transmission +-- group is mandatory for that system. + +-- When Internet-standard definitions for managing +-- transmission media are defined, the transmission group is +-- used to provide a prefix for the names of those objects. + +-- Typically, such definitions reside in the experimental +-- portion of the MIB until they are "proven", then as a +-- part of the Internet standardization process, the +-- definitions are accordingly elevated and a new object +-- identifier, under the transmission group is defined. By +-- convention, the name assigned is: +-- +-- type OBJECT IDENTIFIER ::= { transmission number } +-- +-- where "type" is the symbolic value used for the media in +-- the ifType column of the ifTable object, and "number" is +-- the actual integer value corresponding to the symbol. + + +-- the SNMP group + +-- Implementation of the SNMP group is mandatory for all +-- systems which support an SNMP protocol entity. Some of +-- the objects defined below will be zero-valued in those +-- SNMP implementations that are optimized to support only +-- those functions specific to either a management agent or +-- a management station. In particular, it should be +-- observed that the objects below refer to an SNMP entity, +-- and there may be several SNMP entities residing on a +-- managed node (e.g., if the node is hosting acting as +-- a management station). + + +END diff --git a/libs/smux/RReqPDU.c b/libs/smux/RReqPDU.c new file mode 100644 index 00000000..b19c3548 --- /dev/null +++ b/libs/smux/RReqPDU.c @@ -0,0 +1,107 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "RReqPDU.h" + +static int +memb_priority_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + value = *(const long *)sptr; + + if((value >= -1 && value <= 2147483647)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static asn_TYPE_member_t asn_MBR_RReqPDU_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct RReqPDU, subtree), + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), + 0, + &asn_DEF_ObjectName, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "subtree" + }, + { ATF_NOFLAGS, 0, offsetof(struct RReqPDU, priority), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_NativeInteger, + memb_priority_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "priority" + }, + { ATF_NOFLAGS, 0, offsetof(struct RReqPDU, operation), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "operation" + }, +}; +static ber_tlv_tag_t asn_DEF_RReqPDU_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (2 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_RReqPDU_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 1, 0, 1 }, /* priority at 96 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, -1, 0 }, /* operation at 101 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 } /* subtree at 93 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_RReqPDU_specs_1 = { + sizeof(struct RReqPDU), + offsetof(struct RReqPDU, _asn_ctx), + asn_MAP_RReqPDU_tag2el_1, + 3, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_RReqPDU = { + "RReqPDU", + "RReqPDU", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_RReqPDU_tags_1, + sizeof(asn_DEF_RReqPDU_tags_1) + /sizeof(asn_DEF_RReqPDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_RReqPDU_tags_1, /* Same as above */ + sizeof(asn_DEF_RReqPDU_tags_1) + /sizeof(asn_DEF_RReqPDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + asn_MBR_RReqPDU_1, + 3, /* Elements count */ + &asn_SPC_RReqPDU_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/RRspPDU.c b/libs/smux/RRspPDU.c new file mode 100644 index 00000000..b80080b1 --- /dev/null +++ b/libs/smux/RRspPDU.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "RRspPDU.h" + +int +RRspPDU_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_INTEGER.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using INTEGER, + * so here we adjust the DEF accordingly. + */ +static void +RRspPDU_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_INTEGER.free_struct; + td->print_struct = asn_DEF_INTEGER.print_struct; + td->ber_decoder = asn_DEF_INTEGER.ber_decoder; + td->der_encoder = asn_DEF_INTEGER.der_encoder; + td->xer_decoder = asn_DEF_INTEGER.xer_decoder; + td->xer_encoder = asn_DEF_INTEGER.xer_encoder; + td->uper_decoder = asn_DEF_INTEGER.uper_decoder; + td->uper_encoder = asn_DEF_INTEGER.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_INTEGER.per_constraints; + td->elements = asn_DEF_INTEGER.elements; + td->elements_count = asn_DEF_INTEGER.elements_count; + td->specifics = asn_DEF_INTEGER.specifics; +} + +void +RRspPDU_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + RRspPDU_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +RRspPDU_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + RRspPDU_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +RRspPDU_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + RRspPDU_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +RRspPDU_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + RRspPDU_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +RRspPDU_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + RRspPDU_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +RRspPDU_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + RRspPDU_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_RRspPDU_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (3 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_RRspPDU = { + "RRspPDU", + "RRspPDU", + RRspPDU_free, + RRspPDU_print, + RRspPDU_constraint, + RRspPDU_decode_ber, + RRspPDU_encode_der, + RRspPDU_decode_xer, + RRspPDU_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_RRspPDU_tags_1, + sizeof(asn_DEF_RRspPDU_tags_1) + /sizeof(asn_DEF_RRspPDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_RRspPDU_tags_1, /* Same as above */ + sizeof(asn_DEF_RRspPDU_tags_1) + /sizeof(asn_DEF_RRspPDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* Defined elsewhere */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/SMUX-PDUs.c b/libs/smux/SMUX-PDUs.c new file mode 100644 index 00000000..9942f998 --- /dev/null +++ b/libs/smux/SMUX-PDUs.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "SMUX-PDUs.h" + +static asn_TYPE_member_t asn_MBR_SMUX_PDUs_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct SMUX_PDUs, choice.open), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_OpenPDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "open" + }, + { ATF_NOFLAGS, 0, offsetof(struct SMUX_PDUs, choice.close), + (ASN_TAG_CLASS_APPLICATION | (1 << 2)), + 0, + &asn_DEF_ClosePDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "close" + }, + { ATF_NOFLAGS, 0, offsetof(struct SMUX_PDUs, choice.registerRequest), + (ASN_TAG_CLASS_APPLICATION | (2 << 2)), + 0, + &asn_DEF_RReqPDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "registerRequest" + }, + { ATF_NOFLAGS, 0, offsetof(struct SMUX_PDUs, choice.registerResponse), + (ASN_TAG_CLASS_APPLICATION | (3 << 2)), + 0, + &asn_DEF_RRspPDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "registerResponse" + }, + { ATF_NOFLAGS, 0, offsetof(struct SMUX_PDUs, choice.pdus), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_PDUs, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "pdus" + }, + { ATF_NOFLAGS, 0, offsetof(struct SMUX_PDUs, choice.commitOrRollback), + (ASN_TAG_CLASS_APPLICATION | (4 << 2)), + 0, + &asn_DEF_SOutPDU, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "commitOrRollback" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_SMUX_PDUs_tag2el_1[] = { + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 0, 0, 0 }, /* simple at 52 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 1, 0, 0 }, /* close at 27 */ + { (ASN_TAG_CLASS_APPLICATION | (2 << 2)), 2, 0, 0 }, /* registerRequest at 30 */ + { (ASN_TAG_CLASS_APPLICATION | (3 << 2)), 3, 0, 0 }, /* registerResponse at 33 */ + { (ASN_TAG_CLASS_APPLICATION | (4 << 2)), 5, 0, 0 }, /* commitOrRollback at 41 */ + { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 4, 0, 0 }, /* get-request at 34 */ + { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 4, 0, 0 }, /* get-next-request at 37 */ + { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 4, 0, 0 }, /* get-response at 40 */ + { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 4, 0, 0 }, /* set-request at 43 */ + { (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 4, 0, 0 } /* trap at 47 */ +}; +static asn_CHOICE_specifics_t asn_SPC_SMUX_PDUs_specs_1 = { + sizeof(struct SMUX_PDUs), + offsetof(struct SMUX_PDUs, _asn_ctx), + offsetof(struct SMUX_PDUs, present), + sizeof(((struct SMUX_PDUs *)0)->present), + asn_MAP_SMUX_PDUs_tag2el_1, + 10, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +asn_TYPE_descriptor_t asn_DEF_SMUX_PDUs = { + "SMUX-PDUs", + "SMUX-PDUs", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + 0, /* No PER visible constraints */ + asn_MBR_SMUX_PDUs_1, + 6, /* Elements count */ + &asn_SPC_SMUX_PDUs_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/SMUX.asn1 b/libs/smux/SMUX.asn1 new file mode 100644 index 00000000..af7748fd --- /dev/null +++ b/libs/smux/SMUX.asn1 @@ -0,0 +1,122 @@ + +-- WinAgents MIB Extraction Wizard +-- Extracted from rfc1227.txt 16.03.2005 20:20:14 + +SMUX DEFINITIONS ::= BEGIN + +IMPORTS + ObjectName + FROM RFC1155-SMI + DisplayString + FROM RFC1213-MIB + + PDUs + FROM RFC1157-SNMP; + + +-- tags for SMUX-specific PDUs are application-wide to +-- avoid conflict with tags for current (and future) +-- SNMP-generic PDUs + +SMUX-PDUs ::= + CHOICE { + open -- SMUX peer uses + OpenPDU, -- immediately after TCP open + + close -- either uses immediately before TCP close + ClosePDU, + + registerRequest -- SMUX peer uses + RReqPDU, + + registerResponse -- SNMP agent uses + RRspPDU, + + PDUs, -- note that roles are reversed: + -- SNMP agent does get/get-next/set + -- SMUX peer does get-response/trap + + commitOrRollback -- SNMP agent uses + SOutPDU + } + + +-- open PDU +-- currently only simple authentication + +OpenPDU ::= + CHOICE { + simple + + SimpleOpen + } + +SimpleOpen ::= + [APPLICATION 0] IMPLICIT + SEQUENCE { + version -- of SMUX protocol + INTEGER { + version-1(0) + }, + + identity -- of SMUX peer, authoritative + OBJECT IDENTIFIER, + + description -- of SMUX peer, implementation-specific + DisplayString, + + password -- zero length indicates no authentication + OCTET STRING + } + + +-- close PDU + +ClosePDU ::= + [APPLICATION 1] IMPLICIT + INTEGER { + goingDown(0), + unsupportedVersion(1), + packetFormat(2), + protocolError(3), + internalError(4), + authenticationFailure(5) + } + + +-- insert PDU + +RReqPDU ::= + [APPLICATION 2] IMPLICIT + SEQUENCE { + subtree + ObjectName, + + priority -- the lower the better, "-1" means default + INTEGER (-1..2147483647), + + operation + + INTEGER { + delete(0), -- remove registration + readOnly(1), -- add registration, objects are RO + readWrite(2) -- .., objects are RW + } + } + +RRspPDU ::= + [APPLICATION 3] IMPLICIT + INTEGER { + failure(-1) + + -- on success the non-negative priority is returned + } + +SOutPDU ::= + [APPLICATION 4] IMPLICIT + INTEGER { + commit(0), + rollback(1) + } + +END \ No newline at end of file diff --git a/libs/smux/SOutPDU.c b/libs/smux/SOutPDU.c new file mode 100644 index 00000000..6d3521bf --- /dev/null +++ b/libs/smux/SOutPDU.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "SOutPDU.h" + +int +SOutPDU_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_INTEGER.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using INTEGER, + * so here we adjust the DEF accordingly. + */ +static void +SOutPDU_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_INTEGER.free_struct; + td->print_struct = asn_DEF_INTEGER.print_struct; + td->ber_decoder = asn_DEF_INTEGER.ber_decoder; + td->der_encoder = asn_DEF_INTEGER.der_encoder; + td->xer_decoder = asn_DEF_INTEGER.xer_decoder; + td->xer_encoder = asn_DEF_INTEGER.xer_encoder; + td->uper_decoder = asn_DEF_INTEGER.uper_decoder; + td->uper_encoder = asn_DEF_INTEGER.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_INTEGER.per_constraints; + td->elements = asn_DEF_INTEGER.elements; + td->elements_count = asn_DEF_INTEGER.elements_count; + td->specifics = asn_DEF_INTEGER.specifics; +} + +void +SOutPDU_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + SOutPDU_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +SOutPDU_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + SOutPDU_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +SOutPDU_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + SOutPDU_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +SOutPDU_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + SOutPDU_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +SOutPDU_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + SOutPDU_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +SOutPDU_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + SOutPDU_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_SOutPDU_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (4 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_SOutPDU = { + "SOutPDU", + "SOutPDU", + SOutPDU_free, + SOutPDU_print, + SOutPDU_constraint, + SOutPDU_decode_ber, + SOutPDU_encode_der, + SOutPDU_decode_xer, + SOutPDU_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_SOutPDU_tags_1, + sizeof(asn_DEF_SOutPDU_tags_1) + /sizeof(asn_DEF_SOutPDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_SOutPDU_tags_1, /* Same as above */ + sizeof(asn_DEF_SOutPDU_tags_1) + /sizeof(asn_DEF_SOutPDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* Defined elsewhere */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/SetRequest-PDU.c b/libs/smux/SetRequest-PDU.c new file mode 100644 index 00000000..08d30387 --- /dev/null +++ b/libs/smux/SetRequest-PDU.c @@ -0,0 +1,111 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "SetRequest-PDU.h" + +int +SetRequest_PDU_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + /* Replace with underlying type checker */ + td->check_constraints = asn_DEF_PDU.check_constraints; + return td->check_constraints(td, sptr, ctfailcb, app_key); +} + +/* + * This type is implemented using PDU, + * so here we adjust the DEF accordingly. + */ +static void +SetRequest_PDU_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_PDU.free_struct; + td->print_struct = asn_DEF_PDU.print_struct; + td->ber_decoder = asn_DEF_PDU.ber_decoder; + td->der_encoder = asn_DEF_PDU.der_encoder; + td->xer_decoder = asn_DEF_PDU.xer_decoder; + td->xer_encoder = asn_DEF_PDU.xer_encoder; + td->uper_decoder = asn_DEF_PDU.uper_decoder; + td->uper_encoder = asn_DEF_PDU.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_PDU.per_constraints; + td->elements = asn_DEF_PDU.elements; + td->elements_count = asn_DEF_PDU.elements_count; + td->specifics = asn_DEF_PDU.specifics; +} + +void +SetRequest_PDU_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + SetRequest_PDU_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +SetRequest_PDU_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + SetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +SetRequest_PDU_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + SetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +SetRequest_PDU_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + SetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +SetRequest_PDU_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + SetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +SetRequest_PDU_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + SetRequest_PDU_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_SetRequest_PDU_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (3 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_SetRequest_PDU = { + "SetRequest-PDU", + "SetRequest-PDU", + SetRequest_PDU_free, + SetRequest_PDU_print, + SetRequest_PDU_constraint, + SetRequest_PDU_decode_ber, + SetRequest_PDU_encode_der, + SetRequest_PDU_decode_xer, + SetRequest_PDU_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_SetRequest_PDU_tags_1, + sizeof(asn_DEF_SetRequest_PDU_tags_1) + /sizeof(asn_DEF_SetRequest_PDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_SetRequest_PDU_tags_1, /* Same as above */ + sizeof(asn_DEF_SetRequest_PDU_tags_1) + /sizeof(asn_DEF_SetRequest_PDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* Defined elsewhere */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/SimpleOpen.c b/libs/smux/SimpleOpen.c new file mode 100644 index 00000000..ec267687 --- /dev/null +++ b/libs/smux/SimpleOpen.c @@ -0,0 +1,92 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "SimpleOpen.h" + +static asn_TYPE_member_t asn_MBR_SimpleOpen_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct SimpleOpen, version), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "version" + }, + { ATF_NOFLAGS, 0, offsetof(struct SimpleOpen, identity), + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), + 0, + &asn_DEF_OBJECT_IDENTIFIER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "identity" + }, + { ATF_NOFLAGS, 0, offsetof(struct SimpleOpen, description), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_DisplayString, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "description" + }, + { ATF_NOFLAGS, 0, offsetof(struct SimpleOpen, password), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_OCTET_STRING, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "password" + }, +}; +static ber_tlv_tag_t asn_DEF_SimpleOpen_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_SimpleOpen_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* version at 59 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 2, 0, 1 }, /* description at 66 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 3, -1, 0 }, /* password at 69 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 1, 0, 0 } /* identity at 63 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_SimpleOpen_specs_1 = { + sizeof(struct SimpleOpen), + offsetof(struct SimpleOpen, _asn_ctx), + asn_MAP_SimpleOpen_tag2el_1, + 4, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_SimpleOpen = { + "SimpleOpen", + "SimpleOpen", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_SimpleOpen_tags_1, + sizeof(asn_DEF_SimpleOpen_tags_1) + /sizeof(asn_DEF_SimpleOpen_tags_1[0]) - 1, /* 1 */ + asn_DEF_SimpleOpen_tags_1, /* Same as above */ + sizeof(asn_DEF_SimpleOpen_tags_1) + /sizeof(asn_DEF_SimpleOpen_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + asn_MBR_SimpleOpen_1, + 4, /* Elements count */ + &asn_SPC_SimpleOpen_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/SimpleSyntax.c b/libs/smux/SimpleSyntax.c new file mode 100644 index 00000000..72a11c0a --- /dev/null +++ b/libs/smux/SimpleSyntax.c @@ -0,0 +1,87 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "SimpleSyntax.h" + +static asn_TYPE_member_t asn_MBR_SimpleSyntax_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct SimpleSyntax, choice.number), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "number" + }, + { ATF_NOFLAGS, 0, offsetof(struct SimpleSyntax, choice.string), + (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), + 0, + &asn_DEF_OCTET_STRING, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "string" + }, + { ATF_NOFLAGS, 0, offsetof(struct SimpleSyntax, choice.object), + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), + 0, + &asn_DEF_OBJECT_IDENTIFIER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "object" + }, + { ATF_NOFLAGS, 0, offsetof(struct SimpleSyntax, choice.empty), + (ASN_TAG_CLASS_UNIVERSAL | (5 << 2)), + 0, + &asn_DEF_NULL, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "empty" + }, +}; +static asn_TYPE_tag2member_t asn_MAP_SimpleSyntax_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 0 }, /* number at 73 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 1, 0, 0 }, /* string at 76 */ + { (ASN_TAG_CLASS_UNIVERSAL | (5 << 2)), 3, 0, 0 }, /* empty at 82 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 2, 0, 0 } /* object at 79 */ +}; +static asn_CHOICE_specifics_t asn_SPC_SimpleSyntax_specs_1 = { + sizeof(struct SimpleSyntax), + offsetof(struct SimpleSyntax, _asn_ctx), + offsetof(struct SimpleSyntax, present), + sizeof(((struct SimpleSyntax *)0)->present), + asn_MAP_SimpleSyntax_tag2el_1, + 4, /* Count of tags in the map */ + 0, + -1 /* Extensions start */ +}; +asn_TYPE_descriptor_t asn_DEF_SimpleSyntax = { + "SimpleSyntax", + "SimpleSyntax", + CHOICE_free, + CHOICE_print, + CHOICE_constraint, + CHOICE_decode_ber, + CHOICE_encode_der, + CHOICE_decode_xer, + CHOICE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + CHOICE_outmost_tag, + 0, /* No effective tags (pointer) */ + 0, /* No effective tags (count) */ + 0, /* No tags (pointer) */ + 0, /* No tags (count) */ + 0, /* No PER visible constraints */ + asn_MBR_SimpleSyntax_1, + 4, /* Elements count */ + &asn_SPC_SimpleSyntax_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/TcpConnEntry.c b/libs/smux/TcpConnEntry.c new file mode 100644 index 00000000..1a1c903b --- /dev/null +++ b/libs/smux/TcpConnEntry.c @@ -0,0 +1,151 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "TcpConnEntry.h" + +static int +memb_tcpConnLocalPort_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + value = *(const long *)sptr; + + if((value >= 0 && value <= 65535)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static int +memb_tcpConnRemPort_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + value = *(const long *)sptr; + + if((value >= 0 && value <= 65535)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static asn_TYPE_member_t asn_MBR_TcpConnEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct TcpConnEntry, tcpConnState), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "tcpConnState" + }, + { ATF_NOFLAGS, 0, offsetof(struct TcpConnEntry, tcpConnLocalAddress), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "tcpConnLocalAddress" + }, + { ATF_NOFLAGS, 0, offsetof(struct TcpConnEntry, tcpConnLocalPort), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_NativeInteger, + memb_tcpConnLocalPort_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "tcpConnLocalPort" + }, + { ATF_NOFLAGS, 0, offsetof(struct TcpConnEntry, tcpConnRemAddress), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "tcpConnRemAddress" + }, + { ATF_NOFLAGS, 0, offsetof(struct TcpConnEntry, tcpConnRemPort), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_NativeInteger, + memb_tcpConnRemPort_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "tcpConnRemPort" + }, +}; +static ber_tlv_tag_t asn_DEF_TcpConnEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_TcpConnEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 0, 0, 2 }, /* tcpConnState at 236 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, -1, 1 }, /* tcpConnLocalPort at 240 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 4, -2, 0 }, /* tcpConnRemPort at 244 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 1, 0, 1 }, /* tcpConnLocalAddress at 238 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 3, -1, 0 } /* tcpConnRemAddress at 242 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_TcpConnEntry_specs_1 = { + sizeof(struct TcpConnEntry), + offsetof(struct TcpConnEntry, _asn_ctx), + asn_MAP_TcpConnEntry_tag2el_1, + 5, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_TcpConnEntry = { + "TcpConnEntry", + "TcpConnEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_TcpConnEntry_tags_1, + sizeof(asn_DEF_TcpConnEntry_tags_1) + /sizeof(asn_DEF_TcpConnEntry_tags_1[0]), /* 1 */ + asn_DEF_TcpConnEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_TcpConnEntry_tags_1) + /sizeof(asn_DEF_TcpConnEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_TcpConnEntry_1, + 5, /* Elements count */ + &asn_SPC_TcpConnEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/TimeTicks.c b/libs/smux/TimeTicks.c new file mode 100644 index 00000000..fad39691 --- /dev/null +++ b/libs/smux/TimeTicks.c @@ -0,0 +1,134 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "TimeTicks.h" + +int +TimeTicks_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + const INTEGER_t *st = (const INTEGER_t *)sptr; + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + if(asn_INTEGER2long(st, &value)) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value too large (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + if((value >= 0 && value <= 4294967295)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +/* + * This type is implemented using INTEGER, + * so here we adjust the DEF accordingly. + */ +static void +TimeTicks_1_inherit_TYPE_descriptor(asn_TYPE_descriptor_t *td) { + td->free_struct = asn_DEF_INTEGER.free_struct; + td->print_struct = asn_DEF_INTEGER.print_struct; + td->ber_decoder = asn_DEF_INTEGER.ber_decoder; + td->der_encoder = asn_DEF_INTEGER.der_encoder; + td->xer_decoder = asn_DEF_INTEGER.xer_decoder; + td->xer_encoder = asn_DEF_INTEGER.xer_encoder; + td->uper_decoder = asn_DEF_INTEGER.uper_decoder; + td->uper_encoder = asn_DEF_INTEGER.uper_encoder; + if(!td->per_constraints) + td->per_constraints = asn_DEF_INTEGER.per_constraints; + td->elements = asn_DEF_INTEGER.elements; + td->elements_count = asn_DEF_INTEGER.elements_count; + td->specifics = asn_DEF_INTEGER.specifics; +} + +void +TimeTicks_free(asn_TYPE_descriptor_t *td, + void *struct_ptr, int contents_only) { + TimeTicks_1_inherit_TYPE_descriptor(td); + td->free_struct(td, struct_ptr, contents_only); +} + +int +TimeTicks_print(asn_TYPE_descriptor_t *td, const void *struct_ptr, + int ilevel, asn_app_consume_bytes_f *cb, void *app_key) { + TimeTicks_1_inherit_TYPE_descriptor(td); + return td->print_struct(td, struct_ptr, ilevel, cb, app_key); +} + +asn_dec_rval_t +TimeTicks_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const void *bufptr, size_t size, int tag_mode) { + TimeTicks_1_inherit_TYPE_descriptor(td); + return td->ber_decoder(opt_codec_ctx, td, structure, bufptr, size, tag_mode); +} + +asn_enc_rval_t +TimeTicks_encode_der(asn_TYPE_descriptor_t *td, + void *structure, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + TimeTicks_1_inherit_TYPE_descriptor(td); + return td->der_encoder(td, structure, tag_mode, tag, cb, app_key); +} + +asn_dec_rval_t +TimeTicks_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **structure, const char *opt_mname, const void *bufptr, size_t size) { + TimeTicks_1_inherit_TYPE_descriptor(td); + return td->xer_decoder(opt_codec_ctx, td, structure, opt_mname, bufptr, size); +} + +asn_enc_rval_t +TimeTicks_encode_xer(asn_TYPE_descriptor_t *td, void *structure, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + TimeTicks_1_inherit_TYPE_descriptor(td); + return td->xer_encoder(td, structure, ilevel, flags, cb, app_key); +} + +static ber_tlv_tag_t asn_DEF_TimeTicks_tags_1[] = { + (ASN_TAG_CLASS_APPLICATION | (3 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)) +}; +asn_TYPE_descriptor_t asn_DEF_TimeTicks = { + "TimeTicks", + "TimeTicks", + TimeTicks_free, + TimeTicks_print, + TimeTicks_constraint, + TimeTicks_decode_ber, + TimeTicks_encode_der, + TimeTicks_decode_xer, + TimeTicks_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_TimeTicks_tags_1, + sizeof(asn_DEF_TimeTicks_tags_1) + /sizeof(asn_DEF_TimeTicks_tags_1[0]) - 1, /* 1 */ + asn_DEF_TimeTicks_tags_1, /* Same as above */ + sizeof(asn_DEF_TimeTicks_tags_1) + /sizeof(asn_DEF_TimeTicks_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + 0, 0, /* No members */ + 0 /* No specifics */ +}; + diff --git a/libs/smux/Trap-PDU.c b/libs/smux/Trap-PDU.c new file mode 100644 index 00000000..5e82ddf7 --- /dev/null +++ b/libs/smux/Trap-PDU.c @@ -0,0 +1,112 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "Trap-PDU.h" + +static asn_TYPE_member_t asn_MBR_Trap_PDU_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct Trap_PDU, enterprise), + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), + 0, + &asn_DEF_OBJECT_IDENTIFIER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "enterprise" + }, + { ATF_NOFLAGS, 0, offsetof(struct Trap_PDU, agent_addr), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_NetworkAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "agent-addr" + }, + { ATF_NOFLAGS, 0, offsetof(struct Trap_PDU, generic_trap), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "generic-trap" + }, + { ATF_NOFLAGS, 0, offsetof(struct Trap_PDU, specific_trap), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_INTEGER, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "specific-trap" + }, + { ATF_NOFLAGS, 0, offsetof(struct Trap_PDU, time_stamp), + (ASN_TAG_CLASS_APPLICATION | (3 << 2)), + 0, + &asn_DEF_TimeTicks, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "time-stamp" + }, + { ATF_NOFLAGS, 0, offsetof(struct Trap_PDU, variable_bindings), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_VarBindList, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "variable-bindings" + }, +}; +static ber_tlv_tag_t asn_DEF_Trap_PDU_tags_1[] = { + (ASN_TAG_CLASS_CONTEXT | (4 << 2)), + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_Trap_PDU_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 2, 0, 1 }, /* generic-trap at 106 */ + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 3, -1, 0 }, /* specific-trap at 116 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 0 }, /* enterprise at 99 */ + { (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), 5, 0, 0 }, /* variable-bindings at 125 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 1, 0, 0 }, /* internet at 113 */ + { (ASN_TAG_CLASS_APPLICATION | (3 << 2)), 4, 0, 0 } /* time-stamp at 120 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_Trap_PDU_specs_1 = { + sizeof(struct Trap_PDU), + offsetof(struct Trap_PDU, _asn_ctx), + asn_MAP_Trap_PDU_tag2el_1, + 6, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_Trap_PDU = { + "Trap-PDU", + "Trap-PDU", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_Trap_PDU_tags_1, + sizeof(asn_DEF_Trap_PDU_tags_1) + /sizeof(asn_DEF_Trap_PDU_tags_1[0]) - 1, /* 1 */ + asn_DEF_Trap_PDU_tags_1, /* Same as above */ + sizeof(asn_DEF_Trap_PDU_tags_1) + /sizeof(asn_DEF_Trap_PDU_tags_1[0]), /* 2 */ + 0, /* No PER visible constraints */ + asn_MBR_Trap_PDU_1, + 6, /* Elements count */ + &asn_SPC_Trap_PDU_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/UdpEntry.c b/libs/smux/UdpEntry.c new file mode 100644 index 00000000..711bbadc --- /dev/null +++ b/libs/smux/UdpEntry.c @@ -0,0 +1,96 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "UdpEntry.h" + +static int +memb_udpLocalPort_constraint_1(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + long value; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, sptr, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + value = *(const long *)sptr; + + if((value >= 0 && value <= 65535)) { + /* Constraint check succeeded */ + return 0; + } else { + _ASN_CTFAIL(app_key, td, sptr, + "%s: constraint failed (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +static asn_TYPE_member_t asn_MBR_UdpEntry_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct UdpEntry, udpLocalAddress), + (ASN_TAG_CLASS_APPLICATION | (0 << 2)), + 0, + &asn_DEF_IpAddress, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "udpLocalAddress" + }, + { ATF_NOFLAGS, 0, offsetof(struct UdpEntry, udpLocalPort), + (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), + 0, + &asn_DEF_NativeInteger, + memb_udpLocalPort_constraint_1, + 0, /* PER is not compiled, use -gen-PER */ + 0, + "udpLocalPort" + }, +}; +static ber_tlv_tag_t asn_DEF_UdpEntry_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_UdpEntry_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 1, 0, 0 }, /* udpLocalPort at 253 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 0, 0, 0 } /* udpLocalAddress at 251 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_UdpEntry_specs_1 = { + sizeof(struct UdpEntry), + offsetof(struct UdpEntry, _asn_ctx), + asn_MAP_UdpEntry_tag2el_1, + 2, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_UdpEntry = { + "UdpEntry", + "UdpEntry", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_UdpEntry_tags_1, + sizeof(asn_DEF_UdpEntry_tags_1) + /sizeof(asn_DEF_UdpEntry_tags_1[0]), /* 1 */ + asn_DEF_UdpEntry_tags_1, /* Same as above */ + sizeof(asn_DEF_UdpEntry_tags_1) + /sizeof(asn_DEF_UdpEntry_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_UdpEntry_1, + 2, /* Elements count */ + &asn_SPC_UdpEntry_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/VarBind.c b/libs/smux/VarBind.c new file mode 100644 index 00000000..85a6f97f --- /dev/null +++ b/libs/smux/VarBind.c @@ -0,0 +1,79 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "VarBind.h" + +static asn_TYPE_member_t asn_MBR_VarBind_1[] = { + { ATF_NOFLAGS, 0, offsetof(struct VarBind, name), + (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), + 0, + &asn_DEF_ObjectName, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "name" + }, + { ATF_NOFLAGS, 0, offsetof(struct VarBind, value), + -1 /* Ambiguous tag (CHOICE?) */, + 0, + &asn_DEF_ObjectSyntax, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "value" + }, +}; +static ber_tlv_tag_t asn_DEF_VarBind_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_TYPE_tag2member_t asn_MAP_VarBind_tag2el_1[] = { + { (ASN_TAG_CLASS_UNIVERSAL | (2 << 2)), 1, 0, 0 }, /* number at 73 */ + { (ASN_TAG_CLASS_UNIVERSAL | (4 << 2)), 1, 0, 0 }, /* string at 76 */ + { (ASN_TAG_CLASS_UNIVERSAL | (5 << 2)), 1, 0, 0 }, /* empty at 82 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 0, 0, 1 }, /* name at 133 */ + { (ASN_TAG_CLASS_UNIVERSAL | (6 << 2)), 1, -1, 0 }, /* object at 79 */ + { (ASN_TAG_CLASS_APPLICATION | (0 << 2)), 1, 0, 0 }, /* internet at 113 */ + { (ASN_TAG_CLASS_APPLICATION | (1 << 2)), 1, 0, 0 }, /* counter at 91 */ + { (ASN_TAG_CLASS_APPLICATION | (2 << 2)), 1, 0, 0 }, /* gauge at 94 */ + { (ASN_TAG_CLASS_APPLICATION | (3 << 2)), 1, 0, 0 }, /* ticks at 97 */ + { (ASN_TAG_CLASS_APPLICATION | (4 << 2)), 1, 0, 0 } /* arbitrary at 104 */ +}; +static asn_SEQUENCE_specifics_t asn_SPC_VarBind_specs_1 = { + sizeof(struct VarBind), + offsetof(struct VarBind, _asn_ctx), + asn_MAP_VarBind_tag2el_1, + 10, /* Count of tags in the map */ + 0, 0, 0, /* Optional elements (not needed) */ + -1, /* Start extensions */ + -1 /* Stop extensions */ +}; +asn_TYPE_descriptor_t asn_DEF_VarBind = { + "VarBind", + "VarBind", + SEQUENCE_free, + SEQUENCE_print, + SEQUENCE_constraint, + SEQUENCE_decode_ber, + SEQUENCE_encode_der, + SEQUENCE_decode_xer, + SEQUENCE_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_VarBind_tags_1, + sizeof(asn_DEF_VarBind_tags_1) + /sizeof(asn_DEF_VarBind_tags_1[0]), /* 1 */ + asn_DEF_VarBind_tags_1, /* Same as above */ + sizeof(asn_DEF_VarBind_tags_1) + /sizeof(asn_DEF_VarBind_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_VarBind_1, + 2, /* Elements count */ + &asn_SPC_VarBind_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/VarBindList.c b/libs/smux/VarBindList.c new file mode 100644 index 00000000..15018ded --- /dev/null +++ b/libs/smux/VarBindList.c @@ -0,0 +1,54 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#include + +#include "VarBindList.h" + +static asn_TYPE_member_t asn_MBR_VarBindList_1[] = { + { ATF_POINTER, 0, 0, + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)), + 0, + &asn_DEF_VarBind, + 0, /* Defer constraints checking to the member type */ + 0, /* PER is not compiled, use -gen-PER */ + 0, + "" + }, +}; +static ber_tlv_tag_t asn_DEF_VarBindList_tags_1[] = { + (ASN_TAG_CLASS_UNIVERSAL | (16 << 2)) +}; +static asn_SET_OF_specifics_t asn_SPC_VarBindList_specs_1 = { + sizeof(struct VarBindList), + offsetof(struct VarBindList, _asn_ctx), + 0, /* XER encoding is XMLDelimitedItemList */ +}; +asn_TYPE_descriptor_t asn_DEF_VarBindList = { + "VarBindList", + "VarBindList", + SEQUENCE_OF_free, + SEQUENCE_OF_print, + SEQUENCE_OF_constraint, + SEQUENCE_OF_decode_ber, + SEQUENCE_OF_encode_der, + SEQUENCE_OF_decode_xer, + SEQUENCE_OF_encode_xer, + 0, 0, /* No PER support, use "-gen-PER" to enable */ + 0, /* Use generic outmost tag fetcher */ + asn_DEF_VarBindList_tags_1, + sizeof(asn_DEF_VarBindList_tags_1) + /sizeof(asn_DEF_VarBindList_tags_1[0]), /* 1 */ + asn_DEF_VarBindList_tags_1, /* Same as above */ + sizeof(asn_DEF_VarBindList_tags_1) + /sizeof(asn_DEF_VarBindList_tags_1[0]), /* 1 */ + 0, /* No PER visible constraints */ + asn_MBR_VarBindList_1, + 1, /* Single element */ + &asn_SPC_VarBindList_specs_1 /* Additional specs */ +}; + diff --git a/libs/smux/asn_SEQUENCE_OF.c b/libs/smux/asn_SEQUENCE_OF.c new file mode 100644 index 00000000..ec952fc9 --- /dev/null +++ b/libs/smux/asn_SEQUENCE_OF.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +typedef A_SEQUENCE_OF(void) asn_sequence; + +void +asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free) { + asn_sequence *as = (asn_sequence *)asn_sequence_of_x; + + if(as) { + void *ptr; + int n; + + if(number < 0 || number >= as->count) + return; /* Nothing to delete */ + + if(_do_free && as->free) { + ptr = as->array[number]; + } else { + ptr = 0; + } + + /* + * Shift all elements to the left to hide the gap. + */ + --as->count; + for(n = number; n < as->count; n++) + as->array[n] = as->array[n+1]; + + /* + * Invoke the third-party function only when the state + * of the parent structure is consistent. + */ + if(ptr) as->free(ptr); + } +} + diff --git a/libs/smux/asn_SET_OF.c b/libs/smux/asn_SET_OF.c new file mode 100644 index 00000000..944f2cb8 --- /dev/null +++ b/libs/smux/asn_SET_OF.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Add another element into the set. + */ +int +asn_set_add(void *asn_set_of_x, void *ptr) { + asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x); + + if(as == 0 || ptr == 0) { + errno = EINVAL; /* Invalid arguments */ + return -1; + } + + /* + * Make sure there's enough space to insert an element. + */ + if(as->count == as->size) { + int _newsize = as->size ? (as->size << 1) : 4; + void *_new_arr; + _new_arr = REALLOC(as->array, _newsize * sizeof(as->array[0])); + if(_new_arr) { + as->array = (void **)_new_arr; + as->size = _newsize; + } else { + /* ENOMEM */ + return -1; + } + } + + as->array[as->count++] = ptr; + + return 0; +} + +void +asn_set_del(void *asn_set_of_x, int number, int _do_free) { + asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x); + + if(as) { + void *ptr; + if(number < 0 || number >= as->count) + return; + + if(_do_free && as->free) { + ptr = as->array[number]; + } else { + ptr = 0; + } + + as->array[number] = as->array[--as->count]; + + /* + * Invoke the third-party function only when the state + * of the parent structure is consistent. + */ + if(ptr) as->free(ptr); + } +} + +/* + * Free the contents of the set, do not free the set itself. + */ +void +asn_set_empty(void *asn_set_of_x) { + asn_anonymous_set_ *as = _A_SET_FROM_VOID(asn_set_of_x); + + if(as) { + if(as->array) { + if(as->free) { + while(as->count--) + as->free(as->array[as->count]); + } + FREEMEM(as->array); + as->array = 0; + } + as->count = 0; + as->size = 0; + } + +} + diff --git a/libs/smux/asn_codecs_prim.c b/libs/smux/asn_codecs_prim.c new file mode 100644 index 00000000..4e5c6393 --- /dev/null +++ b/libs/smux/asn_codecs_prim.c @@ -0,0 +1,295 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Decode an always-primitive type. + */ +asn_dec_rval_t +ber_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **sptr, const void *buf_ptr, size_t size, int tag_mode) { + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)*sptr; + asn_dec_rval_t rval; + ber_tlv_len_t length; + + /* + * If the structure is not there, allocate it. + */ + if(st == NULL) { + st = (ASN__PRIMITIVE_TYPE_t *)CALLOC(1, sizeof(*st)); + if(st == NULL) _ASN_DECODE_FAILED; + *sptr = (void *)st; + } + + ASN_DEBUG("Decoding %s as plain primitive (tm=%d)", + td->name, tag_mode); + + /* + * Check tags and extract value length. + */ + rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size, + tag_mode, 0, &length, 0); + if(rval.code != RC_OK) + return rval; + + ASN_DEBUG("%s length is %d bytes", td->name, (int)length); + + /* + * Make sure we have this length. + */ + buf_ptr = ((const char *)buf_ptr) + rval.consumed; + size -= rval.consumed; + if(length > (ber_tlv_len_t)size) { + rval.code = RC_WMORE; + rval.consumed = 0; + return rval; + } + + st->size = (int)length; + /* The following better be optimized away. */ + if(sizeof(st->size) != sizeof(length) + && (ber_tlv_len_t)st->size != length) { + st->size = 0; + _ASN_DECODE_FAILED; + } + + st->buf = (uint8_t *)MALLOC(length + 1); + if(!st->buf) { + st->size = 0; + _ASN_DECODE_FAILED; + } + + memcpy(st->buf, buf_ptr, length); + st->buf[length] = '\0'; /* Just in case */ + + rval.code = RC_OK; + rval.consumed += length; + + ASN_DEBUG("Took %ld/%ld bytes to encode %s", + (long)rval.consumed, + (long)length, td->name); + + return rval; +} + +/* + * Encode an always-primitive type using DER. + */ +asn_enc_rval_t +der_encode_primitive(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t erval; + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; + + ASN_DEBUG("%s %s as a primitive type (tm=%d)", + cb?"Encoding":"Estimating", td->name, tag_mode); + + erval.encoded = der_write_tags(td, st->size, tag_mode, 0, tag, + cb, app_key); + ASN_DEBUG("%s wrote tags %d", td->name, (int)erval.encoded); + if(erval.encoded == -1) { + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + + if(cb && st->buf) { + if(cb(st->buf, st->size, app_key) < 0) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = sptr; + return erval; + } + } else { + assert(st->buf || st->size == 0); + } + + erval.encoded += st->size; + _ASN_ENCODED_OK(erval); +} + +void +ASN__PRIMITIVE_TYPE_free(asn_TYPE_descriptor_t *td, void *sptr, + int contents_only) { + ASN__PRIMITIVE_TYPE_t *st = (ASN__PRIMITIVE_TYPE_t *)sptr; + + if(!td || !sptr) + return; + + ASN_DEBUG("Freeing %s as a primitive type", td->name); + + if(st->buf) + FREEMEM(st->buf); + + if(!contents_only) + FREEMEM(st); +} + + +/* + * Local internal type passed around as an argument. + */ +struct xdp_arg_s { + asn_TYPE_descriptor_t *type_descriptor; + void *struct_key; + xer_primitive_body_decoder_f *prim_body_decoder; + int decoded_something; + int want_more; +}; + + +static int +xer_decode__unexpected_tag(void *key, const void *chunk_buf, size_t chunk_size) { + struct xdp_arg_s *arg = (struct xdp_arg_s *)key; + enum xer_pbd_rval bret; + + if(arg->decoded_something) { + if(xer_is_whitespace(chunk_buf, chunk_size)) + return 0; /* Skip it. */ + /* + * Decoding was done once already. Prohibit doing it again. + */ + return -1; + } + + bret = arg->prim_body_decoder(arg->type_descriptor, + arg->struct_key, chunk_buf, chunk_size); + switch(bret) { + case XPBD_SYSTEM_FAILURE: + case XPBD_DECODER_LIMIT: + case XPBD_BROKEN_ENCODING: + break; + case XPBD_BODY_CONSUMED: + /* Tag decoded successfully */ + arg->decoded_something = 1; + /* Fall through */ + case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */ + return 0; + } + + return -1; +} + +static ssize_t +xer_decode__body(void *key, const void *chunk_buf, size_t chunk_size, int have_more) { + struct xdp_arg_s *arg = (struct xdp_arg_s *)key; + enum xer_pbd_rval bret; + + if(arg->decoded_something) { + if(xer_is_whitespace(chunk_buf, chunk_size)) + return chunk_size; + /* + * Decoding was done once already. Prohibit doing it again. + */ + return -1; + } + + if(!have_more) { + /* + * If we've received something like "1", we can't really + * tell whether it is really `1` or `123`, until we know + * that there is no more data coming. + * The have_more argument will be set to 1 once something + * like this is available to the caller of this callback: + * "1want_more = 1; + return -1; + } + + bret = arg->prim_body_decoder(arg->type_descriptor, + arg->struct_key, chunk_buf, chunk_size); + switch(bret) { + case XPBD_SYSTEM_FAILURE: + case XPBD_DECODER_LIMIT: + case XPBD_BROKEN_ENCODING: + break; + case XPBD_BODY_CONSUMED: + /* Tag decoded successfully */ + arg->decoded_something = 1; + /* Fall through */ + case XPBD_NOT_BODY_IGNORE: /* Safe to proceed further */ + return chunk_size; + } + + return -1; +} + + +asn_dec_rval_t +xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, + void **sptr, + size_t struct_size, + const char *opt_mname, + const void *buf_ptr, size_t size, + xer_primitive_body_decoder_f *prim_body_decoder +) { + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + asn_struct_ctx_t s_ctx; + struct xdp_arg_s s_arg; + asn_dec_rval_t rc; + + /* + * Create the structure if does not exist. + */ + if(!*sptr) { + *sptr = CALLOC(1, struct_size); + if(!*sptr) _ASN_DECODE_FAILED; + } + + memset(&s_ctx, 0, sizeof(s_ctx)); + s_arg.type_descriptor = td; + s_arg.struct_key = *sptr; + s_arg.prim_body_decoder = prim_body_decoder; + s_arg.decoded_something = 0; + s_arg.want_more = 0; + + rc = xer_decode_general(opt_codec_ctx, &s_ctx, &s_arg, + xml_tag, buf_ptr, size, + xer_decode__unexpected_tag, xer_decode__body); + switch(rc.code) { + case RC_OK: + if(!s_arg.decoded_something) { + char ch; + ASN_DEBUG("Primitive body is not recognized, " + "supplying empty one"); + /* + * Decoding opportunity has come and gone. + * Where's the result? + * Try to feed with empty body, see if it eats it. + */ + if(prim_body_decoder(s_arg.type_descriptor, + s_arg.struct_key, &ch, 0) + != XPBD_BODY_CONSUMED) { + /* + * This decoder does not like empty stuff. + */ + _ASN_DECODE_FAILED; + } + } + break; + case RC_WMORE: + /* + * Redo the whole thing later. + * We don't have a context to save intermediate parsing state. + */ + rc.consumed = 0; + break; + case RC_FAIL: + rc.consumed = 0; + if(s_arg.want_more) + rc.code = RC_WMORE; + else + _ASN_DECODE_FAILED; + break; + } + return rc; +} + diff --git a/libs/smux/ber_decoder.c b/libs/smux/ber_decoder.c new file mode 100644 index 00000000..601f66c0 --- /dev/null +++ b/libs/smux/ber_decoder.c @@ -0,0 +1,283 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include + +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num; \ + size -= num; \ + consumed_myself += num; \ + } while(0) +#undef RETURN +#define RETURN(_code) do { \ + asn_dec_rval_t rval; \ + rval.code = _code; \ + if(opt_ctx) opt_ctx->step = step; /* Save context */ \ + if(_code == RC_OK || opt_ctx) \ + rval.consumed = consumed_myself; \ + else \ + rval.consumed = 0; /* Context-free */ \ + return rval; \ + } while(0) + +/* + * The BER decoder of any type. + */ +asn_dec_rval_t +ber_decode(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr, const void *ptr, size_t size) { + asn_codec_ctx_t s_codec_ctx; + + /* + * Stack checker requires that the codec context + * must be allocated on the stack. + */ + if(opt_codec_ctx) { + if(opt_codec_ctx->max_stack_size) { + s_codec_ctx = *opt_codec_ctx; + opt_codec_ctx = &s_codec_ctx; + } + } else { + /* If context is not given, be security-conscious anyway */ + memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); + s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX; + opt_codec_ctx = &s_codec_ctx; + } + + /* + * Invoke type-specific decoder. + */ + return type_descriptor->ber_decoder(opt_codec_ctx, type_descriptor, + struct_ptr, /* Pointer to the destination structure */ + ptr, size, /* Buffer and its size */ + 0 /* Default tag mode is 0 */ + ); +} + +/* + * Check the set of >> tags matches the definition. + */ +asn_dec_rval_t +ber_check_tags(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *td, asn_struct_ctx_t *opt_ctx, + const void *ptr, size_t size, int tag_mode, int last_tag_form, + ber_tlv_len_t *last_length, int *opt_tlv_form) { + ssize_t consumed_myself = 0; + ssize_t tag_len; + ssize_t len_len; + ber_tlv_tag_t tlv_tag; + ber_tlv_len_t tlv_len; + ber_tlv_len_t limit_len = -1; + int expect_00_terminators = 0; + int tlv_constr = -1; /* If CHOICE, opt_tlv_form is not given */ + int step = opt_ctx ? opt_ctx->step : 0; /* Where we left previously */ + int tagno; + + /* + * Make sure we didn't exceed the maximum stack size. + */ + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + RETURN(RC_FAIL); + + /* + * So what does all this implicit skip stuff mean? + * Imagine two types, + * A ::= [5] IMPLICIT T + * B ::= [2] EXPLICIT T + * Where T is defined as + * T ::= [4] IMPLICIT SEQUENCE { ... } + * + * Let's say, we are starting to decode type A, given the + * following TLV stream: <5> <0>. What does this mean? + * It means that the type A contains type T which is, + * in turn, empty. + * Remember though, that we are still in A. We cannot + * just pass control to the type T decoder. Why? Because + * the type T decoder expects <4> <0>, not <5> <0>. + * So, we must make sure we are going to receive <5> while + * still in A, then pass control to the T decoder, indicating + * that the tag <4> was implicitly skipped. The decoder of T + * hence will be prepared to treat <4> as valid tag, and decode + * it appropriately. + */ + + tagno = step /* Continuing where left previously */ + + (tag_mode==1?-1:0) + ; + ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)", + td->name, (long)size, tag_mode, step, tagno); + /* assert(td->tags_count >= 1) May not be the case for CHOICE or ANY */ + + if(tag_mode == 0 && tagno == td->tags_count) { + /* + * This must be the _untagged_ ANY type, + * which outermost tag isn't known in advance. + * Fetch the tag and length separately. + */ + tag_len = ber_fetch_tag(ptr, size, &tlv_tag); + switch(tag_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + tlv_constr = BER_TLV_CONSTRUCTED(ptr); + len_len = ber_fetch_length(tlv_constr, + (const char *)ptr + tag_len, size - tag_len, &tlv_len); + switch(len_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + ASN_DEBUG("Advancing %ld in ANY case", + (long)(tag_len + len_len)); + ADVANCE(tag_len + len_len); + } else { + assert(tagno < td->tags_count); /* At least one loop */ + } + for((void)tagno; tagno < td->tags_count; tagno++, step++) { + + /* + * Fetch and process T from TLV. + */ + tag_len = ber_fetch_tag(ptr, size, &tlv_tag); + ASN_DEBUG("Fetching tag from {%p,%ld}: " + "len %ld, step %d, tagno %d got %s", + ptr, (long)size, + (long)tag_len, step, tagno, + ber_tlv_tag_string(tlv_tag)); + switch(tag_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + tlv_constr = BER_TLV_CONSTRUCTED(ptr); + + /* + * If {I}, don't check anything. + * If {I,B,C}, check B and C unless we're at I. + */ + if(tag_mode != 0 && step == 0) { + /* + * We don't expect tag to match here. + * It's just because we don't know how the tag + * is supposed to look like. + */ + } else { + assert(tagno >= 0); /* Guaranteed by the code above */ + if(tlv_tag != td->tags[tagno]) { + /* + * Unexpected tag. Too bad. + */ + ASN_DEBUG("Expected: %s, " + "expectation failed (tn=%d, tm=%d)", + ber_tlv_tag_string(td->tags[tagno]), + tagno, tag_mode + ); + RETURN(RC_FAIL); + } + } + + /* + * Attention: if there are more tags expected, + * ensure that the current tag is presented + * in constructed form (it contains other tags!). + * If this one is the last one, check that the tag form + * matches the one given in descriptor. + */ + if(tagno < (td->tags_count - 1)) { + if(tlv_constr == 0) { + ASN_DEBUG("tlv_constr = %d, expfail", + tlv_constr); + RETURN(RC_FAIL); + } + } else { + if(last_tag_form != tlv_constr + && last_tag_form != -1) { + ASN_DEBUG("last_tag_form %d != %d", + last_tag_form, tlv_constr); + RETURN(RC_FAIL); + } + } + + /* + * Fetch and process L from TLV. + */ + len_len = ber_fetch_length(tlv_constr, + (const char *)ptr + tag_len, size - tag_len, &tlv_len); + ASN_DEBUG("Fetchinig len = %ld", (long)len_len); + switch(len_len) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + } + + /* + * FIXME + * As of today, the chain of tags + * must either contain several indefinite length TLVs, + * or several definite length ones. + * No mixing is allowed. + */ + if(tlv_len == -1) { + /* + * Indefinite length. + */ + if(limit_len == -1) { + expect_00_terminators++; + } else { + ASN_DEBUG("Unexpected indefinite length " + "in a chain of definite lengths"); + RETURN(RC_FAIL); + } + ADVANCE(tag_len + len_len); + continue; + } else { + if(expect_00_terminators) { + ASN_DEBUG("Unexpected definite length " + "in a chain of indefinite lengths"); + RETURN(RC_FAIL); + } + } + + /* + * Check that multiple TLVs specify ever decreasing length, + * which is consistent. + */ + if(limit_len == -1) { + limit_len = tlv_len + tag_len + len_len; + if(limit_len < 0) { + /* Too great tlv_len value? */ + RETURN(RC_FAIL); + } + } else if(limit_len != tlv_len + tag_len + len_len) { + /* + * Inner TLV specifies length which is inconsistent + * with the outer TLV's length value. + */ + ASN_DEBUG("Outer TLV is %ld and inner is %ld", + (long)limit_len, (long)tlv_len); + RETURN(RC_FAIL); + } + + ADVANCE(tag_len + len_len); + + limit_len -= (tag_len + len_len); + if((ssize_t)size > limit_len) { + /* + * Make sure that we won't consume more bytes + * from the parent frame than the inferred limit. + */ + size = limit_len; + } + } + + if(opt_tlv_form) + *opt_tlv_form = tlv_constr; + if(expect_00_terminators) + *last_length = -expect_00_terminators; + else + *last_length = tlv_len; + + RETURN(RC_OK); +} diff --git a/libs/smux/ber_tlv_length.c b/libs/smux/ber_tlv_length.c new file mode 100644 index 00000000..32aa5e54 --- /dev/null +++ b/libs/smux/ber_tlv_length.c @@ -0,0 +1,177 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +ssize_t +ber_fetch_length(int _is_constructed, const void *bufptr, size_t size, + ber_tlv_len_t *len_r) { + const uint8_t *buf = (const uint8_t *)bufptr; + unsigned oct; + + if(size == 0) + return 0; /* Want more */ + + oct = *(const uint8_t *)buf; + if((oct & 0x80) == 0) { + /* + * Short definite length. + */ + *len_r = oct; /* & 0x7F */ + return 1; + } else { + ber_tlv_len_t len; + size_t skipped; + + if(_is_constructed && oct == 0x80) { + *len_r = -1; /* Indefinite length */ + return 1; + } + + if(oct == 0xff) { + /* Reserved in standard for future use. */ + return -1; + } + + oct &= 0x7F; /* Leave only the 7 LS bits */ + for(len = 0, buf++, skipped = 1; + oct && (++skipped <= size); buf++, oct--) { + + len = (len << 8) | *buf; + if(len < 0 + || (len >> ((8 * sizeof(len)) - 8) && oct > 1)) { + /* + * Too large length value. + */ + return -1; + } + } + + if(oct == 0) { + ber_tlv_len_t lenplusepsilon = (size_t)len + 1024; + /* + * Here length may be very close or equal to 2G. + * However, the arithmetics used in some decoders + * may add some (small) quantities to the length, + * to check the resulting value against some limits. + * This may result in integer wrap-around, which + * we try to avoid by checking it earlier here. + */ + if(lenplusepsilon < 0) { + /* Too large length value */ + return -1; + } + + *len_r = len; + return skipped; + } + + return 0; /* Want more */ + } + +} + +ssize_t +ber_skip_length(asn_codec_ctx_t *opt_codec_ctx, + int _is_constructed, const void *ptr, size_t size) { + ber_tlv_len_t vlen; /* Length of V in TLV */ + ssize_t ll; /* Length of L in TLV */ + size_t skip; + + /* + * Make sure we didn't exceed the maximum stack size. + */ + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + return -1; + + /* + * Determine the size of L in TLV. + */ + ll = ber_fetch_length(_is_constructed, ptr, size, &vlen); + if(ll <= 0) return ll; + + /* + * Definite length. + */ + if(vlen >= 0) { + skip = ll + vlen; + if(skip > size) + return 0; /* Want more */ + return skip; + } + + /* + * Indefinite length! + */ + ASN_DEBUG("Skipping indefinite length"); + for(skip = ll, ptr = ((const char *)ptr) + ll, size -= ll;;) { + ber_tlv_tag_t tag; + + /* Fetch the tag */ + ssize_t tl = ber_fetch_tag(ptr, size, &tag); + if(tl <= 0) return tl; + + ll = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + ((const char *)ptr) + tl, size - tl); + if(ll <= 0) return ll; + + skip += tl + ll; + + /* + * This may be the end of the indefinite length structure, + * two consecutive 0 octets. + * Check if it is true. + */ + if(((const uint8_t *)ptr)[0] == 0 + && ((const uint8_t *)ptr)[1] == 0) + return skip; + + ptr = ((const char *)ptr) + tl + ll; + size -= tl + ll; + } + + /* UNREACHABLE */ +} + +size_t +der_tlv_length_serialize(ber_tlv_len_t len, void *bufp, size_t size) { + size_t required_size; /* Size of len encoding */ + uint8_t *buf = (uint8_t *)bufp; + uint8_t *end; + size_t i; + + if(len <= 127) { + /* Encoded in 1 octet */ + if(size) *buf = (uint8_t)len; + return 1; + } + + /* + * Compute the size of the subsequent bytes. + */ + for(required_size = 1, i = 8; i < 8 * sizeof(len); i += 8) { + if(len >> i) + required_size++; + else + break; + } + + if(size <= required_size) + return required_size + 1; + + *buf++ = (uint8_t)(0x80 | required_size); /* Length of the encoding */ + + /* + * Produce the len encoding, space permitting. + */ + end = buf + required_size; + for(i -= 8; buf < end; i -= 8, buf++) + *buf = (uint8_t)(len >> i); + + return required_size + 1; +} + diff --git a/libs/smux/ber_tlv_tag.c b/libs/smux/ber_tlv_tag.c new file mode 100644 index 00000000..42708760 --- /dev/null +++ b/libs/smux/ber_tlv_tag.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +ssize_t +ber_fetch_tag(const void *ptr, size_t size, ber_tlv_tag_t *tag_r) { + ber_tlv_tag_t val; + ber_tlv_tag_t tclass; + size_t skipped; + + if(size == 0) + return 0; + + val = *(const uint8_t *)ptr; + tclass = (val >> 6); + if((val &= 0x1F) != 0x1F) { + /* + * Simple form: everything encoded in a single octet. + * Tag Class is encoded using two least significant bits. + */ + *tag_r = (val << 2) | tclass; + return 1; + } + + /* + * Each octet contains 7 bits of useful information. + * The MSB is 0 if it is the last octet of the tag. + */ + for(val = 0, ptr = ((const char *)ptr) + 1, skipped = 2; + skipped <= size; + ptr = ((const char *)ptr) + 1, skipped++) { + unsigned int oct = *(const uint8_t *)ptr; + if(oct & 0x80) { + val = (val << 7) | (oct & 0x7F); + /* + * Make sure there are at least 9 bits spare + * at the MS side of a value. + */ + if(val >> ((8 * sizeof(val)) - 9)) { + /* + * We would not be able to accomodate + * any more tag bits. + */ + return -1; + } + } else { + val = (val << 7) | oct; + *tag_r = (val << 2) | tclass; + return skipped; + } + } + + return 0; /* Want more */ +} + + +ssize_t +ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *f) { + char buf[sizeof("[APPLICATION ]") + 32]; + ssize_t ret; + + ret = ber_tlv_tag_snprint(tag, buf, sizeof(buf)); + if(ret >= (ssize_t)sizeof(buf) || ret < 2) { + errno = EPERM; + return -1; + } + + return fwrite(buf, 1, ret, f); +} + +ssize_t +ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t size) { + char *type = 0; + int ret; + + switch(tag & 0x3) { + case ASN_TAG_CLASS_UNIVERSAL: type = "UNIVERSAL "; break; + case ASN_TAG_CLASS_APPLICATION: type = "APPLICATION "; break; + case ASN_TAG_CLASS_CONTEXT: type = ""; break; + case ASN_TAG_CLASS_PRIVATE: type = "PRIVATE "; break; + } + + ret = snprintf(buf, size, "[%s%u]", type, ((unsigned)tag) >> 2); + if(ret <= 0 && size) buf[0] = '\0'; /* against broken libc's */ + + return ret; +} + +char * +ber_tlv_tag_string(ber_tlv_tag_t tag) { + static char buf[sizeof("[APPLICATION ]") + 32]; + + (void)ber_tlv_tag_snprint(tag, buf, sizeof(buf)); + + return buf; +} + + +size_t +ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufp, size_t size) { + int tclass = BER_TAG_CLASS(tag); + ber_tlv_tag_t tval = BER_TAG_VALUE(tag); + uint8_t *buf = (uint8_t *)bufp; + uint8_t *end; + size_t required_size; + size_t i; + + if(tval <= 30) { + /* Encoded in 1 octet */ + if(size) buf[0] = (tclass << 6) | tval; + return 1; + } else if(size) { + *buf++ = (tclass << 6) | 0x1F; + size--; + } + + /* + * Compute the size of the subsequent bytes. + */ + for(required_size = 1, i = 7; i < 8 * sizeof(tval); i += 7) { + if(tval >> i) + required_size++; + else + break; + } + + if(size < required_size) + return required_size + 1; + + /* + * Fill in the buffer, space permitting. + */ + end = buf + required_size - 1; + for(i -= 7; buf < end; i -= 7, buf++) + *buf = 0x80 | ((tval >> i) & 0x7F); + *buf = (tval & 0x7F); /* Last octet without high bit */ + + return required_size + 1; +} + diff --git a/libs/smux/constr_CHOICE.c b/libs/smux/constr_CHOICE.c new file mode 100644 index 00000000..a20a0505 --- /dev/null +++ b/libs/smux/constr_CHOICE.c @@ -0,0 +1,1101 @@ +/* + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the 's L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * ... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * See the definitions. + */ +static int _fetch_present_idx(const void *struct_ptr, int off, int size); +static void _set_present_idx(void *sptr, int offset, int size, int pres); + +/* + * Tags are canonically sorted in the tag to member table. + */ +static int +_search4tag(const void *ap, const void *bp) { + const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap; + const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp; + + int a_class = BER_TAG_CLASS(a->el_tag); + int b_class = BER_TAG_CLASS(b->el_tag); + + if(a_class == b_class) { + ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag); + ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag); + + if(a_value == b_value) + return 0; + else if(a_value < b_value) + return -1; + else + return 1; + } else if(a_class < b_class) { + return -1; + } else { + return 1; + } +} + +/* + * The decoder of the CHOICE type. + */ +asn_dec_rval_t +CHOICE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_TYPE_member_t *elements = td->elements; + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + ssize_t tag_len; /* Length of TLV's T */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + ASN_DEBUG("Decoding %s as CHOICE", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + if(tag_mode || td->tags_count) { + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, -1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) { + /* ?Substracted below! */ + ctx->left += rval.consumed; + } + ADVANCE(rval.consumed); + } else { + ctx->left = -1; + } + + NEXT_PHASE(ctx); + + ASN_DEBUG("Structure consumes %ld bytes, buffer %ld", + (long)ctx->left, (long)size); + + /* Fall through */ + case 1: + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + ASN_DEBUG("In %s CHOICE tag length %d", td->name, (int)tag_len); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + do { + asn_TYPE_tag2member_t *t2m; + asn_TYPE_tag2member_t key; + + key.el_tag = tlv_tag; + t2m = (asn_TYPE_tag2member_t *)bsearch(&key, + specs->tag2el, specs->tag2el_count, + sizeof(specs->tag2el[0]), _search4tag); + if(t2m) { + /* + * Found the element corresponding to the tag. + */ + NEXT_PHASE(ctx); + ctx->step = t2m->el_no; + break; + } else if(specs->ext_start == -1) { + ASN_DEBUG("Unexpected tag %s " + "in non-extensible CHOICE %s", + ber_tlv_tag_string(tlv_tag), td->name); + RETURN(RC_FAIL); + } else { + /* Skip this tag */ + ssize_t skip; + + ASN_DEBUG("Skipping unknown tag %s", + ber_tlv_tag_string(tlv_tag)); + + skip = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + (const char *)ptr + tag_len, + LEFT - tag_len); + + switch(skip) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + ADVANCE(skip + tag_len); + RETURN(RC_OK); + } + } while(0); + + case 2: + /* + * PHASE 2. + * Read in the element. + */ + do { + asn_TYPE_member_t *elm;/* CHOICE's element */ + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + elm = &elements[ctx->step]; + + /* + * Compute the position of the member inside a structure, + * and also a type of containment (it may be contained + * as pointer or using inline inclusion). + */ + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + /* + * A pointer to a pointer + * holding the start of the structure + */ + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + /* Set presence to be able to free it properly at any time */ + _set_present_idx(st, specs->pres_offset, + specs->pres_size, ctx->step + 1); + /* + * Invoke the member fetch routine according to member's type + */ + rval = elm->type->ber_decoder(opt_codec_ctx, elm->type, + memb_ptr2, ptr, LEFT, elm->tag_mode); + switch(rval.code) { + case RC_OK: + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + RETURN(RC_FAIL); + case RC_FAIL: /* Fatal error */ + RETURN(rval.code); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } while(0); + + NEXT_PHASE(ctx); + + /* Fall through */ + case 3: + ASN_DEBUG("CHOICE %s Leftover: %ld, size = %ld, tm=%d, tc=%d", + td->name, (long)ctx->left, (long)size, + tag_mode, td->tags_count); + + if(ctx->left > 0) { + /* + * The type must be fully decoded + * by the CHOICE member-specific decoder. + */ + RETURN(RC_FAIL); + } + + if(ctx->left == -1 + && !(tag_mode || td->tags_count)) { + /* + * This is an untagged CHOICE. + * It doesn't contain nothing + * except for the member itself, including all its tags. + * The decoding is completed. + */ + NEXT_PHASE(ctx); + break; + } + + /* + * Read in the "end of data chunks"'s. + */ + while(ctx->left < 0) { + ssize_t tl; + + tl = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tl) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + /* + * Expected <0><0>... + */ + if(((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Correctly finished with <0><0>. + */ + ADVANCE(2); + ctx->left++; + continue; + } + } else { + ASN_DEBUG("Unexpected continuation in %s", + td->name); + RETURN(RC_FAIL); + } + + /* UNREACHABLE */ + } + + NEXT_PHASE(ctx); + case 4: + /* No meaningful work here */ + break; + } + + RETURN(RC_OK); +} + +asn_enc_rval_t +CHOICE_encode_der(asn_TYPE_descriptor_t *td, void *sptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_TYPE_member_t *elm; /* CHOICE element */ + asn_enc_rval_t erval; + void *memb_ptr; + size_t computed_size = 0; + int present; + + if(!sptr) _ASN_ENCODE_FAILED; + + ASN_DEBUG("%s %s as CHOICE", + cb?"Encoding":"Estimating", td->name); + + present = _fetch_present_idx(sptr, + specs->pres_offset, specs->pres_size); + + /* + * If the structure was not initialized, it cannot be encoded: + * can't deduce what to encode in the choice type. + */ + if(present <= 0 || present > td->elements_count) { + if(present == 0 && td->elements_count == 0) { + /* The CHOICE is empty?! */ + erval.encoded = 0; + _ASN_ENCODED_OK(erval); + } + _ASN_ENCODE_FAILED; + } + + /* + * Seek over the present member of the structure. + */ + elm = &td->elements[present-1]; + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(memb_ptr == 0) { + if(elm->optional) { + erval.encoded = 0; + _ASN_ENCODED_OK(erval); + } + /* Mandatory element absent */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + + /* + * If the CHOICE itself is tagged EXPLICIT: + * T ::= [2] EXPLICIT CHOICE { ... } + * Then emit the appropriate tags. + */ + if(tag_mode == 1 || td->tags_count) { + /* + * For this, we need to pre-compute the member. + */ + ssize_t ret; + + /* Encode member with its tag */ + erval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, 0, 0); + if(erval.encoded == -1) + return erval; + + /* Encode CHOICE with parent or my own tag */ + ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag, + cb, app_key); + if(ret == -1) + _ASN_ENCODE_FAILED; + computed_size += ret; + } + + /* + * Encode the single underlying member. + */ + erval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, cb, app_key); + if(erval.encoded == -1) + return erval; + + ASN_DEBUG("Encoded CHOICE member in %ld bytes (+%ld)", + (long)erval.encoded, (long)computed_size); + + erval.encoded += computed_size; + + return erval; +} + +ber_tlv_tag_t +CHOICE_outmost_tag(asn_TYPE_descriptor_t *td, const void *ptr, int tag_mode, ber_tlv_tag_t tag) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + int present; + + assert(tag_mode == 0); (void)tag_mode; + assert(tag == 0); (void)tag; + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size); + + if(present > 0 || present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *) + ((const char *)ptr + elm->memb_offset); + } else { + memb_ptr = (const void *) + ((const char *)ptr + elm->memb_offset); + } + + return asn_TYPE_outmost_tag(elm->type, memb_ptr, + elm->tag_mode, elm->tag); + } else { + return (ber_tlv_tag_t)-1; + } +} + +int +CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + int present; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size); + if(present > 0 && present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) + return 0; + _ASN_CTFAIL(app_key, td, + "%s: mandatory CHOICE element %s absent (%s:%d)", + td->name, elm->name, __FILE__, __LINE__); + return -1; + } + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + if(elm->memb_constraints) { + return elm->memb_constraints(elm->type, memb_ptr, + ctfailcb, app_key); + } else { + int ret = elm->type->check_constraints(elm->type, + memb_ptr, ctfailcb, app_key); + /* + * Cannot inherit it eralier: + * need to make sure we get the updated version. + */ + elm->memb_constraints = elm->type->check_constraints; + return ret; + } + } else { + _ASN_CTFAIL(app_key, td, + "%s: no CHOICE element given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } +} + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value of a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + int edx; /* Element index */ + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + if(ctx->phase == 0 && !*xml_tag) + ctx->phase = 1; /* Skip the outer tag checking phase */ + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + * Phase 3: Only waiting for closing tag. + * Phase 4: Skipping unknown extensions. + * Phase 5: PHASED OUT + */ + for(edx = ctx->step; ctx->phase <= 4;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + asn_TYPE_member_t *elm; + + /* + * Go inside the member. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + elm = &td->elements[edx]; + + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Start/Continue decoding the inner member */ + tmprval = elm->type->xer_decoder(opt_codec_ctx, + elm->type, memb_ptr2, elm->name, + buf_ptr, size); + XER_ADVANCE(tmprval.consumed); + ASN_DEBUG("XER/CHOICE: itdf: [%s] code=%d", + elm->type->name, tmprval.code); + if(tmprval.code != RC_OK) + RETURN(tmprval.code); + assert(_fetch_present_idx(st, + specs->pres_offset, specs->pres_size) == 0); + /* Record what we've got */ + _set_present_idx(st, + specs->pres_offset, specs->pres_size, edx + 1); + ctx->phase = 3; + /* Fall through */ + } + + /* No need to wait for closing tag; special mode. */ + if(ctx->phase == 3 && !*xml_tag) { + ctx->phase = 5; /* Phase out */ + RETURN(RC_OK); + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, buf_ptr, size, &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/CHOICE checked [%c%c%c%c] vs [%s], tcv=%d", + ch_size>0?((const uint8_t *)buf_ptr)[0]:'?', + ch_size>1?((const uint8_t *)buf_ptr)[1]:'?', + ch_size>2?((const uint8_t *)buf_ptr)[2]:'?', + ch_size>3?((const uint8_t *)buf_ptr)[3]:'?', + xml_tag, tcv); + + /* Skip the extensions section */ + if(ctx->phase == 4) { + ASN_DEBUG("skip_unknown(%d, %ld)", + tcv, (long)ctx->left); + switch(xer_skip_unknown(tcv, &ctx->left)) { + case -1: + ctx->phase = 5; + RETURN(RC_FAIL); + continue; + case 1: + ctx->phase = 3; + /* Fall through */ + case 0: + XER_ADVANCE(ch_size); + continue; + case 2: + ctx->phase = 3; + break; + } + } + + switch(tcv) { + case XCT_BOTH: + break; /* No CHOICE? */ + case XCT_CLOSING: + if(ctx->phase != 3) + break; + XER_ADVANCE(ch_size); + ctx->phase = 5; /* Phase out */ + RETURN(RC_OK); + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + if(ctx->phase != 1) + break; /* Really unexpected */ + + /* + * Search which inner member corresponds to this tag. + */ + for(edx = 0; edx < td->elements_count; edx++) { + elm = &td->elements[edx]; + tcv = xer_check_tag(buf_ptr,ch_size,elm->name); + switch(tcv) { + case XCT_BOTH: + case XCT_OPENING: + /* + * Process this member. + */ + ctx->step = edx; + ctx->phase = 2; + break; + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + continue; + default: + edx = td->elements_count; + break; /* Phase out */ + } + break; + } + if(edx != td->elements_count) + continue; + + /* It is expected extension */ + if(specs->ext_start != -1) { + ASN_DEBUG("Got anticipated extension"); + /* + * Check for (XCT_BOTH or XCT_UNKNOWN_BO) + * By using a mask. Only record a pure + * tags. + */ + if(tcv & XCT_CLOSING) { + /* Found without body */ + ctx->phase = 3; /* Terminating */ + } else { + ctx->left = 1; + ctx->phase = 4; /* Skip ...'s */ + } + XER_ADVANCE(ch_size); + continue; + } + + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag [%c%c%c%c] in CHOICE [%s]" + " (ph=%d, tag=%s)", + ch_size>0?((const uint8_t *)buf_ptr)[0]:'?', + ch_size>1?((const uint8_t *)buf_ptr)[1]:'?', + ch_size>2?((const uint8_t *)buf_ptr)[2]:'?', + ch_size>3?((const uint8_t *)buf_ptr)[3]:'?', + td->name, ctx->phase, xml_tag); + break; + } + + ctx->phase = 5; /* Phase out, just in case */ + RETURN(RC_FAIL); +} + + +asn_enc_rval_t +CHOICE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_CHOICE_specifics_t *specs=(asn_CHOICE_specifics_t *)td->specifics; + asn_enc_rval_t er; + int present; + + if(!sptr) + _ASN_ENCODE_FAILED; + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size); + + if(present <= 0 || present > td->elements_count) { + _ASN_ENCODE_FAILED; + } else { + asn_enc_rval_t tmper; + asn_TYPE_member_t *elm = &td->elements[present-1]; + void *memb_ptr; + const char *mname = elm->name; + unsigned int mlen = strlen(mname); + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) _ASN_ENCODE_FAILED; + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + + er.encoded = 0; + + if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + 1, flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + + _ASN_CALLBACK3("", 1); + + er.encoded += 5 + (2 * mlen) + tmper.encoded; + } + + if(!(flags & XER_F_CANONICAL)) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +asn_dec_rval_t +CHOICE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_dec_rval_t rv; + asn_per_constraint_t *ct; + asn_TYPE_member_t *elm; /* CHOICE's element */ + void *memb_ptr; + void **memb_ptr2; + void *st = *sptr; + int value; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted */ + } + + if(ct && ct->range_bits >= 0) { + value = per_get_few_bits(pd, ct->range_bits); + if(value < 0) _ASN_DECODE_STARVED; + ASN_DEBUG("CHOICE %s got index %d in range %d", + td->name, value, ct->range_bits); + if(value > ct->upper_bound) + _ASN_DECODE_FAILED; + } else { + if(specs->ext_start == -1) + _ASN_DECODE_FAILED; + value = uper_get_nsnnwn(pd); + if(value < 0) _ASN_DECODE_STARVED; + value += specs->ext_start; + if(value >= td->elements_count) + _ASN_DECODE_FAILED; + ASN_DEBUG("NOT IMPLEMENTED YET"); + _ASN_DECODE_FAILED; + } + + /* Adjust if canonical order is different from natural order */ + if(specs->canonical_order) + value = specs->canonical_order[value]; + + /* Set presence to be able to free it later */ + _set_present_idx(st, specs->pres_offset, specs->pres_size, value + 1); + + elm = &td->elements[value]; + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + ASN_DEBUG("Discovered CHOICE %s encodes %s", td->name, elm->name); + + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, memb_ptr2, pd); + if(rv.code != RC_OK) + ASN_DEBUG("Failed to decode %s in %s (CHOICE)", + elm->name, td->name); + return rv; +} + +asn_enc_rval_t +CHOICE_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + asn_TYPE_member_t *elm; /* CHOICE's element */ + asn_per_constraint_t *ct; + void *memb_ptr; + int present; + + if(!sptr) _ASN_ENCODE_FAILED; + + ASN_DEBUG("Encoding %s as CHOICE", td->name); + + if(constraints) ct = &constraints->value; + else if(td->per_constraints) ct = &td->per_constraints->value; + else ct = 0; + + present = _fetch_present_idx(sptr, + specs->pres_offset, specs->pres_size); + + /* + * If the structure was not initialized properly, it cannot be encoded: + * can't deduce what to encode in the choice type. + */ + if(present <= 0 || present > td->elements_count) + _ASN_ENCODE_FAILED; + else + present--; + + /* Adjust if canonical order is different from natural order */ + if(specs->canonical_order) + present = specs->canonical_order[present]; + + ASN_DEBUG("Encoding %s CHOICE element %d", td->name, present); + + if(ct && ct->range_bits >= 0) { + if(present < ct->lower_bound + || present > ct->upper_bound) { + if(ct->flags & APC_EXTENSIBLE) { + if(per_put_few_bits(po, 1, 1)) + _ASN_ENCODE_FAILED; + } else { + _ASN_ENCODE_FAILED; + } + ct = 0; + } + } + if(ct && ct->flags & APC_EXTENSIBLE) + if(per_put_few_bits(po, 0, 1)) + _ASN_ENCODE_FAILED; + + if(ct && ct->range_bits >= 0) { + if(per_put_few_bits(po, present, ct->range_bits)) + _ASN_ENCODE_FAILED; + } else { + if(specs->ext_start == -1) + _ASN_ENCODE_FAILED; + if(uper_put_nsnnwn(po, present - specs->ext_start)) + _ASN_ENCODE_FAILED; + ASN_DEBUG("NOT IMPLEMENTED YET"); + _ASN_ENCODE_FAILED; + } + + elm = &td->elements[present]; + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) _ASN_ENCODE_FAILED; + } else { + memb_ptr = (char *)sptr + elm->memb_offset; + } + + return elm->type->uper_encoder(elm->type, elm->per_constraints, + memb_ptr, po); +} + + +int +CHOICE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics; + int present; + + if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(sptr, specs->pres_offset,specs->pres_size); + + /* + * Print that element. + */ + if(present > 0 && present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + /* Print member's name and stuff */ + if(0) { + if(cb(elm->name, strlen(elm->name), app_key) < 0 + || cb(": ", 2, app_key) < 0) + return -1; + } + + return elm->type->print_struct(elm->type, memb_ptr, ilevel, + cb, app_key); + } else { + return (cb("", 8, app_key) < 0) ? -1 : 0; + } +} + +void +CHOICE_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + asn_CHOICE_specifics_t *specs = td ? (asn_CHOICE_specifics_t *)td->specifics : NULL; + int present; + + if(!td || !ptr) + return; + + ASN_DEBUG("Freeing %s as CHOICE", td->name); + + /* + * Figure out which CHOICE element is encoded. + */ + present = _fetch_present_idx(ptr, specs->pres_offset, specs->pres_size); + + /* + * Free that element. + */ + if(present > 0 && present <= td->elements_count) { + asn_TYPE_member_t *elm = &td->elements[present-1]; + void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)ptr + elm->memb_offset); + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } else { + memb_ptr = (void *)((char *)ptr + elm->memb_offset); + ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); + } + } + + if(!contents_only) { + FREEMEM(ptr); + } +} + + +/* + * The following functions functions offer protection against -fshort-enums, + * compatible with little- and big-endian machines. + * If assertion is triggered, either disable -fshort-enums, or add an entry + * here with the ->pres_size of your target stracture. + * Unless the target structure is packed, the ".present" member + * is guaranteed to be aligned properly. ASN.1 compiler itself does not + * produce packed code. + */ +static int +_fetch_present_idx(const void *struct_ptr, int pres_offset, int pres_size) { + const void *present_ptr; + int present; + + present_ptr = ((const char *)struct_ptr) + pres_offset; + + switch(pres_size) { + case sizeof(int): present = *(const int *)present_ptr; break; + case sizeof(short): present = *(const short *)present_ptr; break; + case sizeof(char): present = *(const char *)present_ptr; break; + default: + /* ANSI C mandates enum to be equivalent to integer */ + assert(pres_size != sizeof(int)); + return 0; /* If not aborted, pass back safe value */ + } + + return present; +} + +static void +_set_present_idx(void *struct_ptr, int pres_offset, int pres_size, int present) { + void *present_ptr; + present_ptr = ((char *)struct_ptr) + pres_offset; + + switch(pres_size) { + case sizeof(int): *(int *)present_ptr = present; break; + case sizeof(short): *(short *)present_ptr = present; break; + case sizeof(char): *(char *)present_ptr = present; break; + default: + /* ANSI C mandates enum to be equivalent to integer */ + assert(pres_size != sizeof(int)); + } +} diff --git a/libs/smux/constr_SEQUENCE.c b/libs/smux/constr_SEQUENCE.c new file mode 100644 index 00000000..bc14ca5e --- /dev/null +++ b/libs/smux/constr_SEQUENCE.c @@ -0,0 +1,1251 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the 's L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * ... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#undef PHASE_OUT +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) +#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * Check whether we are inside the extensions group. + */ +#define IN_EXTENSION_GROUP(specs, memb_idx) \ + ( ((memb_idx) > (specs)->ext_after) \ + &&((memb_idx) < (specs)->ext_before)) + + +/* + * Tags are canonically sorted in the tag2element map. + */ +static int +_t2e_cmp(const void *ap, const void *bp) { + const asn_TYPE_tag2member_t *a = (const asn_TYPE_tag2member_t *)ap; + const asn_TYPE_tag2member_t *b = (const asn_TYPE_tag2member_t *)bp; + + int a_class = BER_TAG_CLASS(a->el_tag); + int b_class = BER_TAG_CLASS(b->el_tag); + + if(a_class == b_class) { + ber_tlv_tag_t a_value = BER_TAG_VALUE(a->el_tag); + ber_tlv_tag_t b_value = BER_TAG_VALUE(b->el_tag); + + if(a_value == b_value) { + if(a->el_no > b->el_no) + return 1; + /* + * Important: we do not check + * for a->el_no <= b->el_no! + */ + return 0; + } else if(a_value < b_value) + return -1; + else + return 1; + } else if(a_class < b_class) { + return -1; + } else { + return 1; + } +} + + +/* + * The decoder of the SEQUENCE type. + */ +asn_dec_rval_t +SEQUENCE_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; + asn_TYPE_member_t *elements = td->elements; + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + int edx; /* SEQUENCE element's index */ + + ASN_DEBUG("Decoding %s as SEQUENCE", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, 1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) + ctx->left += rval.consumed; /* ?Substracted below! */ + ADVANCE(rval.consumed); + + NEXT_PHASE(ctx); + + ASN_DEBUG("Structure consumes %ld bytes, buffer %ld", + (long)ctx->left, (long)size); + + /* Fall through */ + case 1: + /* + * PHASE 1. + * From the place where we've left it previously, + * try to decode the next member from the list of + * this structure's elements. + * (ctx->step) stores the member being processed + * between invocations and the microphase {0,1} of parsing + * that member: + * step = ( * 2 + ). + */ + for(edx = (ctx->step >> 1); edx < td->elements_count; + edx++, ctx->step = (ctx->step & ~1) + 2) { + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + ssize_t tag_len; /* Length of TLV's T */ + int opt_edx_end; /* Next non-optional element */ + int use_bsearch; + int n; + + if(ctx->step & 1) + goto microphase2; + + /* + * MICROPHASE 1: Synchronize decoding. + */ + ASN_DEBUG("In %s SEQUENCE left %d, edx=%d flags=%d" + " opt=%d ec=%d", + td->name, (int)ctx->left, edx, + elements[edx].flags, elements[edx].optional, + td->elements_count); + + if(ctx->left == 0 /* No more stuff is expected */ + && ( + /* Explicit OPTIONAL specification reaches the end */ + (edx + elements[edx].optional + == td->elements_count) + || + /* All extensions are optional */ + (IN_EXTENSION_GROUP(specs, edx) + && specs->ext_before > td->elements_count) + ) + ) { + ASN_DEBUG("End of SEQUENCE %s", td->name); + /* + * Found the legitimate end of the structure. + */ + PHASE_OUT(ctx); + RETURN(RC_OK); + } + + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + ASN_DEBUG("Current tag in %s SEQUENCE for element %d " + "(%s) is %s encoded in %d bytes, of frame %ld", + td->name, edx, elements[edx].name, + ber_tlv_tag_string(tlv_tag), (int)tag_len, (long)LEFT); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + ASN_DEBUG("edx = %d, opt = %d, ec=%d", + edx, elements[edx].optional, + td->elements_count); + if((edx + elements[edx].optional + == td->elements_count) + || (IN_EXTENSION_GROUP(specs, edx) + && specs->ext_before + > td->elements_count)) { + /* + * Yeah, baby! Found the terminator + * of the indefinite length structure. + */ + /* + * Proceed to the canonical + * finalization function. + * No advancing is necessary. + */ + goto phase3; + } + } + } + + /* + * Find the next available type with this tag. + */ + use_bsearch = 0; + opt_edx_end = edx + elements[edx].optional + 1; + if(opt_edx_end > td->elements_count) + opt_edx_end = td->elements_count; /* Cap */ + else if(opt_edx_end - edx > 8) { + /* Limit the scope of linear search... */ + opt_edx_end = edx + 8; + use_bsearch = 1; + /* ... and resort to bsearch() */ + } + for(n = edx; n < opt_edx_end; n++) { + if(BER_TAGS_EQUAL(tlv_tag, elements[n].tag)) { + /* + * Found element corresponding to the tag + * being looked at. + * Reposition over the right element. + */ + edx = n; + ctx->step = 1 + 2 * edx; /* Remember! */ + goto microphase2; + } else if(elements[n].flags & ATF_OPEN_TYPE) { + /* + * This is the ANY type, which may bear + * any flag whatsoever. + */ + edx = n; + ctx->step = 1 + 2 * edx; /* Remember! */ + goto microphase2; + } else if(elements[n].tag == (ber_tlv_tag_t)-1) { + use_bsearch = 1; + break; + } + } + if(use_bsearch) { + /* + * Resort to a binary search over + * sorted array of tags. + */ + asn_TYPE_tag2member_t *t2m; + asn_TYPE_tag2member_t key; + key.el_tag = tlv_tag; + key.el_no = edx; + t2m = (asn_TYPE_tag2member_t *)bsearch(&key, + specs->tag2el, specs->tag2el_count, + sizeof(specs->tag2el[0]), _t2e_cmp); + if(t2m) { + asn_TYPE_tag2member_t *best = 0; + asn_TYPE_tag2member_t *t2m_f, *t2m_l; + int edx_max = edx + elements[edx].optional; + /* + * Rewind to the first element with that tag, + * `cause bsearch() does not guarantee order. + */ + t2m_f = t2m + t2m->toff_first; + t2m_l = t2m + t2m->toff_last; + for(t2m = t2m_f; t2m <= t2m_l; t2m++) { + if(t2m->el_no > edx_max) break; + if(t2m->el_no < edx) continue; + best = t2m; + } + if(best) { + edx = best->el_no; + ctx->step = 1 + 2 * edx; + goto microphase2; + } + } + n = opt_edx_end; + } + if(n == opt_edx_end) { + /* + * If tag is unknown, it may be either + * an unknown (thus, incorrect) tag, + * or an extension (...), + * or an end of the indefinite-length structure. + */ + if(!IN_EXTENSION_GROUP(specs, edx)) { + ASN_DEBUG("Unexpected tag %s (at %d)", + ber_tlv_tag_string(tlv_tag), edx); + ASN_DEBUG("Expected tag %s (%s)%s", + ber_tlv_tag_string(elements[edx].tag), + elements[edx].name, + elements[edx].optional + ?" or alternatives":""); + RETURN(RC_FAIL); + } else { + /* Skip this tag */ + ssize_t skip; + + skip = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + (const char *)ptr + tag_len, + LEFT - tag_len); + ASN_DEBUG("Skip length %d in %s", + (int)skip, td->name); + switch(skip) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + ADVANCE(skip + tag_len); + ctx->step -= 2; + edx--; + continue; /* Try again with the next tag */ + } + } + + /* + * MICROPHASE 2: Invoke the member-specific decoder. + */ + ctx->step |= 1; /* Confirm entering next microphase */ + microphase2: + ASN_DEBUG("Inside SEQUENCE %s MF2", td->name); + + /* + * Compute the position of the member inside a structure, + * and also a type of containment (it may be contained + * as pointer or using inline inclusion). + */ + if(elements[edx].flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + elements[edx].memb_offset); + } else { + /* + * A pointer to a pointer + * holding the start of the structure + */ + memb_ptr = (char *)st + elements[edx].memb_offset; + memb_ptr2 = &memb_ptr; + } + /* + * Invoke the member fetch routine according to member's type + */ + rval = elements[edx].type->ber_decoder(opt_codec_ctx, + elements[edx].type, + memb_ptr2, ptr, LEFT, + elements[edx].tag_mode); + ASN_DEBUG("In %s SEQUENCE decoded %d %s of %d " + "in %d bytes rval.code %d, size=%d", + td->name, edx, elements[edx].type->name, + (int)LEFT, (int)rval.consumed, rval.code, (int)size); + switch(rval.code) { + case RC_OK: + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + ASN_DEBUG("Size violation (c->l=%ld <= s=%ld)", + (long)ctx->left, (long)size); + /* Fall through */ + case RC_FAIL: /* Fatal error */ + RETURN(RC_FAIL); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } /* for(all structure members) */ + + phase3: + ctx->phase = 3; + case 3: /* 00 and other tags expected */ + case 4: /* only 00's expected */ + + ASN_DEBUG("SEQUENCE %s Leftover: %ld, size = %ld", + td->name, (long)ctx->left, (long)size); + + /* + * Skip everything until the end of the SEQUENCE. + */ + while(ctx->left) { + ssize_t tl, ll; + + tl = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tl) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + /* + * If expected <0><0>... + */ + if(ctx->left < 0 + && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Correctly finished with <0><0>. + */ + ADVANCE(2); + ctx->left++; + ctx->phase = 4; + continue; + } + } + + if(!IN_EXTENSION_GROUP(specs, td->elements_count) + || ctx->phase == 4) { + ASN_DEBUG("Unexpected continuation " + "of a non-extensible type " + "%s (SEQUENCE): %s", + td->name, + ber_tlv_tag_string(tlv_tag)); + RETURN(RC_FAIL); + } + + ll = ber_skip_length(opt_codec_ctx, + BER_TLV_CONSTRUCTED(ptr), + (const char *)ptr + tl, LEFT - tl); + switch(ll) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + ADVANCE(tl + ll); + } + + PHASE_OUT(ctx); + } + + RETURN(RC_OK); +} + + +/* + * The DER encoder of the SEQUENCE type. + */ +asn_enc_rval_t +SEQUENCE_encode_der(asn_TYPE_descriptor_t *td, + void *sptr, int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + size_t computed_size = 0; + asn_enc_rval_t erval; + ssize_t ret; + int edx; + + ASN_DEBUG("%s %s as SEQUENCE", + cb?"Encoding":"Estimating", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) continue; + /* Mandatory element is missing */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + erval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, + 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + ASN_DEBUG("Member %d %s estimated %ld bytes", + edx, elm->name, (long)erval.encoded); + } + + /* + * Encode the TLV for the sequence itself. + */ + ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key); + ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size); + if(ret == -1) + _ASN_ENCODE_FAILED; + erval.encoded = computed_size + ret; + + if(!cb) _ASN_ENCODED_OK(erval); + + /* + * Encode all members. + */ + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + asn_enc_rval_t tmperval; + void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) continue; + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + tmperval = elm->type->der_encoder(elm->type, memb_ptr, + elm->tag_mode, elm->tag, + cb, app_key); + if(tmperval.encoded == -1) + return tmperval; + computed_size -= tmperval.encoded; + ASN_DEBUG("Member %d %s of SEQUENCE %s encoded in %ld bytes", + edx, elm->name, td->name, (long)tmperval.encoded); + } + + if(computed_size != 0) + /* + * Encoded size is not equal to the computed size. + */ + _ASN_ENCODE_FAILED; + + _ASN_ENCODED_OK(erval); +} + + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_SEQUENCE_specifics_t *specs + = (asn_SEQUENCE_specifics_t *)td->specifics; + asn_TYPE_member_t *elements = td->elements; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * ... and parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value from a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + int edx; /* Element index */ + int edx_end; + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + * Phase 3: Skipping unknown extensions. + * Phase 4: PHASED OUT + */ + for(edx = ctx->step; ctx->phase <= 3;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + asn_TYPE_member_t *elm; + + /* + * Go inside the inner member of a sequence. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + elm = &td->elements[edx]; + + if(elm->flags & ATF_POINTER) { + /* Member is a pointer to another structure */ + memb_ptr2 = (void **)((char *)st + + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Invoke the inner type decoder, m.b. multiple times */ + tmprval = elm->type->xer_decoder(opt_codec_ctx, + elm->type, memb_ptr2, elm->name, + buf_ptr, size); + XER_ADVANCE(tmprval.consumed); + if(tmprval.code != RC_OK) + RETURN(tmprval.code); + ctx->phase = 1; /* Back to body processing */ + ctx->step = ++edx; + ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d", + ctx->phase, ctx->step); + /* Fall through */ + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, buf_ptr, size, + &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d [%s]", + tcv, ctx->phase, xml_tag); + + /* Skip the extensions section */ + if(ctx->phase == 3) { + switch(xer_skip_unknown(tcv, &ctx->left)) { + case -1: + ctx->phase = 4; + RETURN(RC_FAIL); + case 0: + XER_ADVANCE(ch_size); + continue; + case 1: + XER_ADVANCE(ch_size); + ctx->phase = 1; + continue; + case 2: + ctx->phase = 1; + break; + } + } + + switch(tcv) { + case XCT_CLOSING: + if(ctx->phase == 0) break; + ctx->phase = 0; + /* Fall through */ + case XCT_BOTH: + if(ctx->phase == 0) { + if(edx >= td->elements_count + || + /* Explicit OPTIONAL specs reaches the end */ + (edx + elements[edx].optional + == td->elements_count) + || + /* All extensions are optional */ + (IN_EXTENSION_GROUP(specs, edx) + && specs->ext_before + > td->elements_count) + ) { + XER_ADVANCE(ch_size); + ctx->phase = 4; /* Phase out */ + RETURN(RC_OK); + } else { + ASN_DEBUG("Premature end of XER SEQUENCE"); + RETURN(RC_FAIL); + } + } + /* Fall through */ + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d, edx=%d", + tcv, ctx->phase, edx); + if(ctx->phase != 1) { + break; /* Really unexpected */ + } + + if(edx < td->elements_count) { + /* + * Search which member corresponds to this tag. + */ + edx_end = edx + elements[edx].optional + 1; + if(edx_end > td->elements_count) + edx_end = td->elements_count; + int n; + for(n = edx; n < edx_end; n++) { + elm = &td->elements[n]; + tcv = xer_check_tag(buf_ptr, + ch_size, elm->name); + switch(tcv) { + case XCT_BOTH: + case XCT_OPENING: + /* + * Process this member. + */ + ctx->step = edx = n; + ctx->phase = 2; + break; + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + continue; + default: + n = edx_end; + break; /* Phase out */ + } + break; + } + if(n != edx_end) + continue; + } else { + ASN_DEBUG("Out of defined members: %d/%d", + edx, td->elements_count); + } + + /* It is expected extension */ + if(IN_EXTENSION_GROUP(specs, + edx + (edx < td->elements_count + ? elements[edx].optional : 0))) { + ASN_DEBUG("Got anticipated extension at %d", + edx); + /* + * Check for (XCT_BOTH or XCT_UNKNOWN_BO) + * By using a mask. Only record a pure + * tags. + */ + if(tcv & XCT_CLOSING) { + /* Found without body */ + } else { + ctx->left = 1; + ctx->phase = 3; /* Skip ...'s */ + } + XER_ADVANCE(ch_size); + continue; + } + + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag in SEQUENCE [%c%c%c%c%c%c]", + size>0?((const char *)buf_ptr)[0]:'.', + size>1?((const char *)buf_ptr)[1]:'.', + size>2?((const char *)buf_ptr)[2]:'.', + size>3?((const char *)buf_ptr)[3]:'.', + size>4?((const char *)buf_ptr)[4]:'.', + size>5?((const char *)buf_ptr)[5]:'.'); + break; + } + + ctx->phase = 4; /* "Phase out" on hard failure */ + RETURN(RC_FAIL); +} + +asn_enc_rval_t +SEQUENCE_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + int xcan = (flags & XER_F_CANONICAL); + int edx; + + if(!sptr) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + for(edx = 0; edx < td->elements_count; edx++) { + asn_enc_rval_t tmper; + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; + const char *mname = elm->name; + unsigned int mlen = strlen(mname); + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) + continue; + /* Mandatory element is missing */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + + /* Print the member itself */ + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + 1, flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + + _ASN_CALLBACK3("", 1); + er.encoded += 5 + (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +int +SEQUENCE_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + int edx; + int ret; + + if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb(td->name, strlen(td->name), app_key) < 0 + || cb(" ::= {", 6, app_key) < 0) + return -1; + + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) continue; + /* Print line */ + /* Fall through */ + } + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + /* Indentation */ + _i_INDENT(1); + + /* Print the member's name and stuff */ + if(cb(elm->name, strlen(elm->name), app_key) < 0 + || cb(": ", 2, app_key) < 0) + return -1; + + /* Print the member itself */ + ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1, + cb, app_key); + if(ret) return ret; + } + + ilevel--; + _i_INDENT(1); + + return (cb("}", 1, app_key) < 0) ? -1 : 0; +} + +void +SEQUENCE_free(asn_TYPE_descriptor_t *td, void *sptr, int contents_only) { + int edx; + + if(!td || !sptr) + return; + + ASN_DEBUG("Freeing %s as SEQUENCE", td->name); + + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; + if(elm->flags & ATF_POINTER) { + memb_ptr = *(void **)((char *)sptr + elm->memb_offset); + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + ASN_STRUCT_FREE_CONTENTS_ONLY(*elm->type, memb_ptr); + } + } + + if(!contents_only) { + FREEMEM(sptr); + } +} + +int +SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + int edx; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + /* + * Iterate over structure members and check their validity. + */ + for(edx = 0; edx < td->elements_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + const void *memb_ptr; + + if(elm->flags & ATF_POINTER) { + memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset); + if(!memb_ptr) { + if(elm->optional) + continue; + _ASN_CTFAIL(app_key, td, + "%s: mandatory element %s absent (%s:%d)", + td->name, elm->name, __FILE__, __LINE__); + return -1; + } + } else { + memb_ptr = (const void *)((const char *)sptr + elm->memb_offset); + } + + if(elm->memb_constraints) { + int ret = elm->memb_constraints(elm->type, memb_ptr, + ctfailcb, app_key); + if(ret) return ret; + } else { + int ret = elm->type->check_constraints(elm->type, + memb_ptr, ctfailcb, app_key); + if(ret) return ret; + /* + * Cannot inherit it earlier: + * need to make sure we get the updated version. + */ + elm->memb_constraints = elm->type->check_constraints; + } + } + + return 0; +} + +asn_dec_rval_t +SEQUENCE_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics; + void *st = *sptr; /* Target structure. */ + int extpresent = 0; /* Extension additions are present */ + uint8_t *opres; /* Presence of optional root members */ + asn_per_data_t opmd; + asn_dec_rval_t rv; + int edx; + + (void)constraints; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + + ASN_DEBUG("Decoding %s as SEQUENCE (UPER)", td->name); + + /* Handle extensions */ + if(specs->ext_before >= 0) { + extpresent = per_get_few_bits(pd, 1); + if(extpresent < 0) _ASN_DECODE_STARVED; + } + + /* Prepare a place and read-in the presence bitmap */ + if(specs->roms_count) { + opres = (uint8_t *)MALLOC(((specs->roms_count + 7) >> 3) + 1); + if(!opres) _ASN_DECODE_FAILED; + /* Get the presence map */ + if(per_get_many_bits(pd, opres, 0, specs->roms_count)) { + FREEMEM(opres); + _ASN_DECODE_STARVED; + } + opmd.buffer = opres; + opmd.nboff = 0; + opmd.nbits = specs->roms_count; + ASN_DEBUG("Read in presence bitmap for %s of %d bits (%x..)", + td->name, specs->roms_count, *opres); + } else { + opres = 0; + memset(&opmd, 0, sizeof opmd); + } + + /* + * Get the sequence ROOT elements. + */ + for(edx = 0; edx < ((specs->ext_before < 0) + ? td->elements_count : specs->ext_before + 1); edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)st + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Deal with optionality */ + if(elm->optional) { + int present = per_get_few_bits(&opmd, 1); + ASN_DEBUG("Member %s->%s is optional, p=%d (%d->%d)", + td->name, elm->name, present, + (int)opmd.nboff, (int)opmd.nbits); + if(present == 0) { + /* This element is not present */ + if(elm->default_value) { + /* Fill-in DEFAULT */ + if(elm->default_value(1, memb_ptr2)) { + FREEMEM(opres); + _ASN_DECODE_FAILED; + } + } + /* The member is just not present */ + continue; + } + /* Fall through */ + } + + /* Fetch the member from the stream */ + ASN_DEBUG("Decoding member %s in %s", elm->name, td->name); + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, memb_ptr2, pd); + if(rv.code != RC_OK) { + ASN_DEBUG("Failed decode %s in %s", + elm->name, td->name); + FREEMEM(opres); + return rv; + } + } + + /* + * Deal with extensions. + */ + if(extpresent) { + ASN_DEBUG("Extensibility for %s: NOT IMPLEMENTED", td->name); + _ASN_DECODE_FAILED; + } else { + for(edx = specs->roms_count; edx < specs->roms_count + + specs->aoms_count; edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + if(!elm->default_value) continue; + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)st + + elm->memb_offset); + } else { + memb_ptr = (char *)st + elm->memb_offset; + memb_ptr2 = &memb_ptr; + } + + /* Set default value */ + if(elm->default_value(1, memb_ptr2)) { + FREEMEM(opres); + _ASN_DECODE_FAILED; + } + } + } + + rv.consumed = 0; + rv.code = RC_OK; + FREEMEM(opres); + return rv; +} + +asn_enc_rval_t +SEQUENCE_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_SEQUENCE_specifics_t *specs + = (asn_SEQUENCE_specifics_t *)td->specifics; + asn_enc_rval_t er; + int edx; + int i; + + (void)constraints; + + if(!sptr) + _ASN_ENCODE_FAILED; + + er.encoded = 0; + + ASN_DEBUG("Encoding %s as SEQUENCE (UPER)", td->name); + if(specs->ext_before >= 0) + _ASN_ENCODE_FAILED; /* We don't encode extensions yet */ + + /* Encode a presence bitmap */ + for(i = 0; i < specs->roms_count; i++) { + asn_TYPE_member_t *elm; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + int present; + + edx = specs->oms[i]; + elm = &td->elements[edx]; + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + present = (*memb_ptr2 != 0); + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr2 = &memb_ptr; + present = 1; + } + + /* Eliminate default values */ + if(present && elm->default_value + && elm->default_value(0, memb_ptr2) == 1) + present = 0; + + ASN_DEBUG("Element %s %s %s->%s is %s", + elm->flags & ATF_POINTER ? "ptr" : "inline", + elm->default_value ? "def" : "wtv", + td->name, elm->name, present ? "present" : "absent"); + if(per_put_few_bits(po, present, 1)) + _ASN_ENCODE_FAILED; + } + + /* + * Get the sequence ROOT elements. + */ + for(edx = 0; edx < ((specs->ext_before < 0) + ? td->elements_count : specs->ext_before + 1); edx++) { + asn_TYPE_member_t *elm = &td->elements[edx]; + void *memb_ptr; /* Pointer to the member */ + void **memb_ptr2; /* Pointer to that pointer */ + + /* Fetch the pointer to this member */ + if(elm->flags & ATF_POINTER) { + memb_ptr2 = (void **)((char *)sptr + elm->memb_offset); + if(!*memb_ptr2) { + ASN_DEBUG("Element %s %d not present", + elm->name, edx); + if(elm->optional) + continue; + /* Mandatory element is missing */ + _ASN_ENCODE_FAILED; + } + } else { + memb_ptr = (void *)((char *)sptr + elm->memb_offset); + memb_ptr2 = &memb_ptr; + } + + /* Eliminate default values */ + if(elm->default_value && elm->default_value(0, memb_ptr2) == 1) + continue; + + er = elm->type->uper_encoder(elm->type, elm->per_constraints, + *memb_ptr2, po); + if(er.encoded == -1) + return er; + } + + _ASN_ENCODED_OK(er); +} + diff --git a/libs/smux/constr_SEQUENCE_OF.c b/libs/smux/constr_SEQUENCE_OF.c new file mode 100644 index 00000000..aa101176 --- /dev/null +++ b/libs/smux/constr_SEQUENCE_OF.c @@ -0,0 +1,208 @@ +/*- + * Copyright (c) 2003, 2004, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * The DER encoder of the SEQUENCE OF type. + */ +asn_enc_rval_t +SEQUENCE_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(ptr); + size_t computed_size = 0; + ssize_t encoding_size = 0; + asn_enc_rval_t erval; + int edx; + + ASN_DEBUG("Estimating size of SEQUENCE OF %s", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = elm->type->der_encoder(elm->type, memb_ptr, + 0, elm->tag, + 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + } + + /* + * Encode the TLV for the sequence itself. + */ + encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, + cb, app_key); + if(encoding_size == -1) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + computed_size += encoding_size; + if(!cb) { + erval.encoded = computed_size; + _ASN_ENCODED_OK(erval); + } + + ASN_DEBUG("Encoding members of SEQUENCE OF %s", td->name); + + /* + * Encode all members. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = elm->type->der_encoder(elm->type, memb_ptr, + 0, elm->tag, + cb, app_key); + if(erval.encoded == -1) + return erval; + encoding_size += erval.encoded; + } + + if(computed_size != (size_t)encoding_size) { + /* + * Encoded size is not equal to the computed size. + */ + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + } else { + erval.encoded = computed_size; + erval.structure_ptr = 0; + erval.failed_type = 0; + } + + return erval; +} + +asn_enc_rval_t +SEQUENCE_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_sequence_ *list = _A_SEQUENCE_FROM_VOID(sptr); + const char *mname = specs->as_XMLValueList + ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag); + unsigned int mlen = mname ? strlen(mname) : 0; + int xcan = (flags & XER_F_CANONICAL); + int i; + + if(!sptr) _ASN_ENCODE_FAILED; + + er.encoded = 0; + + for(i = 0; i < list->count; i++) { + asn_enc_rval_t tmper; + void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + if(mname) { + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + } + + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + 1, flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + if(tmper.encoded == 0 && specs->as_XMLValueList) { + const char *name = elm->type->xml_tag; + size_t len = strlen(name); + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel + 1); + _ASN_CALLBACK3("<", 1, name, len, "/>", 2); + } + + if(mname) { + _ASN_CALLBACK3("", 1); + er.encoded += 5; + } + + er.encoded += (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +asn_enc_rval_t +SEQUENCE_OF_encode_uper(asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) { + asn_anonymous_sequence_ *list; + asn_per_constraint_t *ct; + asn_enc_rval_t er; + asn_TYPE_member_t *elm = td->elements; + int seq; + + if(!sptr) _ASN_ENCODE_FAILED; + list = _A_SEQUENCE_FROM_VOID(sptr); + + er.encoded = 0; + + ASN_DEBUG("Encoding %s as SEQUENCE OF (%d)", td->name, list->count); + + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + /* If extensible constraint, check if size is in root */ + if(ct) { + int not_in_root = (list->count < ct->lower_bound + || list->count > ct->upper_bound); + ASN_DEBUG("lb %ld ub %ld %s", + ct->lower_bound, ct->upper_bound, + ct->flags & APC_EXTENSIBLE ? "ext" : "fix"); + if(ct->flags & APC_EXTENSIBLE) { + /* Declare whether size is in extension root */ + if(per_put_few_bits(po, not_in_root, 1)) + _ASN_ENCODE_FAILED; + if(not_in_root) ct = 0; + } else if(not_in_root && ct->effective_bits >= 0) + _ASN_ENCODE_FAILED; + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ + if(per_put_few_bits(po, list->count - ct->lower_bound, + ct->effective_bits)) + _ASN_ENCODE_FAILED; + } + + for(seq = -1; seq < list->count;) { + ssize_t mayEncode; + if(seq < 0) seq = 0; + if(ct && ct->effective_bits >= 0) { + mayEncode = list->count; + } else { + mayEncode = uper_put_length(po, list->count - seq); + if(mayEncode < 0) _ASN_ENCODE_FAILED; + } + + while(mayEncode--) { + void *memb_ptr = list->array[seq++]; + if(!memb_ptr) _ASN_ENCODE_FAILED; + er = elm->type->uper_encoder(elm->type, + elm->per_constraints, memb_ptr, po); + if(er.encoded == -1) + _ASN_ENCODE_FAILED; + } + } + + _ASN_ENCODED_OK(er); +} + diff --git a/libs/smux/constr_SET_OF.c b/libs/smux/constr_SET_OF.c new file mode 100644 index 00000000..0d5efa4f --- /dev/null +++ b/libs/smux/constr_SET_OF.c @@ -0,0 +1,942 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Number of bytes left for this structure. + * (ctx->left) indicates the number of bytes _transferred_ for the structure. + * (size) contains the number of bytes in the buffer passed. + */ +#define LEFT ((size<(size_t)ctx->left)?size:(size_t)ctx->left) + +/* + * If the subprocessor function returns with an indication that it wants + * more data, it may well be a fatal decoding problem, because the + * size is constrained by the 's L, even if the buffer size allows + * reading more data. + * For example, consider the buffer containing the following TLVs: + * ... + * The TLV length clearly indicates that one byte is expected in V, but + * if the V processor returns with "want more data" even if the buffer + * contains way more data than the V processor have seen. + */ +#define SIZE_VIOLATION (ctx->left >= 0 && (size_t)ctx->left <= size) + +/* + * This macro "eats" the part of the buffer which is definitely "consumed", + * i.e. was correctly converted into local representation or rightfully skipped. + */ +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + ptr = ((const char *)ptr) + num;\ + size -= num; \ + if(ctx->left >= 0) \ + ctx->left -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Switch to the next phase of parsing. + */ +#undef NEXT_PHASE +#undef PHASE_OUT +#define NEXT_PHASE(ctx) do { \ + ctx->phase++; \ + ctx->step = 0; \ + } while(0) +#define PHASE_OUT(ctx) do { ctx->phase = 10; } while(0) + +/* + * Return a standardized complex structure. + */ +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself;\ + return rval; \ + } while(0) + +/* + * The decoder of the SET OF type. + */ +asn_dec_rval_t +SET_OF_decode_ber(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *ptr, size_t size, int tag_mode) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + + /* + * Parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + ber_tlv_tag_t tlv_tag; /* T from TLV */ + asn_dec_rval_t rval; /* Return code from subparsers */ + + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + ASN_DEBUG("Decoding %s as SET OF", td->name); + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) { + RETURN(RC_FAIL); + } + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Start to parse where left previously + */ + switch(ctx->phase) { + case 0: + /* + * PHASE 0. + * Check that the set of tags associated with given structure + * perfectly fits our expectations. + */ + + rval = ber_check_tags(opt_codec_ctx, td, ctx, ptr, size, + tag_mode, 1, &ctx->left, 0); + if(rval.code != RC_OK) { + ASN_DEBUG("%s tagging check failed: %d", + td->name, rval.code); + return rval; + } + + if(ctx->left >= 0) + ctx->left += rval.consumed; /* ?Substracted below! */ + ADVANCE(rval.consumed); + + ASN_DEBUG("Structure consumes %ld bytes, " + "buffer %ld", (long)ctx->left, (long)size); + + NEXT_PHASE(ctx); + /* Fall through */ + case 1: + /* + * PHASE 1. + * From the place where we've left it previously, + * try to decode the next item. + */ + for(;; ctx->step = 0) { + ssize_t tag_len; /* Length of TLV's T */ + + if(ctx->step & 1) + goto microphase2; + + /* + * MICROPHASE 1: Synchronize decoding. + */ + + if(ctx->left == 0) { + ASN_DEBUG("End of SET OF %s", td->name); + /* + * No more things to decode. + * Exit out of here. + */ + PHASE_OUT(ctx); + RETURN(RC_OK); + } + + /* + * Fetch the T from TLV. + */ + tag_len = ber_fetch_tag(ptr, LEFT, &tlv_tag); + switch(tag_len) { + case 0: if(!SIZE_VIOLATION) RETURN(RC_WMORE); + /* Fall through */ + case -1: RETURN(RC_FAIL); + } + + if(ctx->left < 0 && ((const uint8_t *)ptr)[0] == 0) { + if(LEFT < 2) { + if(SIZE_VIOLATION) + RETURN(RC_FAIL); + else + RETURN(RC_WMORE); + } else if(((const uint8_t *)ptr)[1] == 0) { + /* + * Found the terminator of the + * indefinite length structure. + */ + break; + } + } + + /* Outmost tag may be unknown and cannot be fetched/compared */ + if(elm->tag != (ber_tlv_tag_t)-1) { + if(BER_TAGS_EQUAL(tlv_tag, elm->tag)) { + /* + * The new list member of expected type has arrived. + */ + } else { + ASN_DEBUG("Unexpected tag %s fixed SET OF %s", + ber_tlv_tag_string(tlv_tag), td->name); + ASN_DEBUG("%s SET OF has tag %s", + td->name, ber_tlv_tag_string(elm->tag)); + RETURN(RC_FAIL); + } + } + + /* + * MICROPHASE 2: Invoke the member-specific decoder. + */ + ctx->step |= 1; /* Confirm entering next microphase */ + microphase2: + + /* + * Invoke the member fetch routine according to member's type + */ + rval = elm->type->ber_decoder(opt_codec_ctx, + elm->type, &ctx->ptr, ptr, LEFT, 0); + ASN_DEBUG("In %s SET OF %s code %d consumed %d", + td->name, elm->type->name, + rval.code, (int)rval.consumed); + switch(rval.code) { + case RC_OK: + { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + else + ctx->ptr = 0; + } + break; + case RC_WMORE: /* More data expected */ + if(!SIZE_VIOLATION) { + ADVANCE(rval.consumed); + RETURN(RC_WMORE); + } + /* Fall through */ + case RC_FAIL: /* Fatal error */ + RETURN(RC_FAIL); + } /* switch(rval) */ + + ADVANCE(rval.consumed); + } /* for(all list members) */ + + NEXT_PHASE(ctx); + case 2: + /* + * Read in all "end of content" TLVs. + */ + while(ctx->left < 0) { + if(LEFT < 2) { + if(LEFT > 0 && ((const char *)ptr)[0] != 0) { + /* Unexpected tag */ + RETURN(RC_FAIL); + } else { + RETURN(RC_WMORE); + } + } + if(((const char *)ptr)[0] == 0 + && ((const char *)ptr)[1] == 0) { + ADVANCE(2); + ctx->left++; + } else { + RETURN(RC_FAIL); + } + } + + PHASE_OUT(ctx); + } + + RETURN(RC_OK); +} + +/* + * Internally visible buffer holding a single encoded element. + */ +struct _el_buffer { + uint8_t *buf; + size_t length; + size_t size; +}; +/* Append bytes to the above structure */ +static int _el_addbytes(const void *buffer, size_t size, void *el_buf_ptr) { + struct _el_buffer *el_buf = (struct _el_buffer *)el_buf_ptr; + + if(el_buf->length + size > el_buf->size) + return -1; + + memcpy(el_buf->buf + el_buf->length, buffer, size); + + el_buf->length += size; + return 0; +} +static int _el_buf_cmp(const void *ap, const void *bp) { + const struct _el_buffer *a = (const struct _el_buffer *)ap; + const struct _el_buffer *b = (const struct _el_buffer *)bp; + int ret; + size_t common_len; + + if(a->length < b->length) + common_len = a->length; + else + common_len = b->length; + + ret = memcmp(a->buf, b->buf, common_len); + if(ret == 0) { + if(a->length < b->length) + ret = -1; + else if(a->length > b->length) + ret = 1; + } + + return ret; +} + +/* + * The DER encoder of the SET OF type. + */ +asn_enc_rval_t +SET_OF_encode_der(asn_TYPE_descriptor_t *td, void *ptr, + int tag_mode, ber_tlv_tag_t tag, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_TYPE_descriptor_t *elm_type = elm->type; + der_type_encoder_f *der_encoder = elm_type->der_encoder; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); + size_t computed_size = 0; + ssize_t encoding_size = 0; + struct _el_buffer *encoded_els; + ssize_t eels_count = 0; + size_t max_encoded_len = 1; + asn_enc_rval_t erval; + int ret; + int edx; + + ASN_DEBUG("Estimating size for SET OF %s", td->name); + + /* + * Gather the length of the underlying members sequence. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + if(!memb_ptr) continue; + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, 0, 0); + if(erval.encoded == -1) + return erval; + computed_size += erval.encoded; + + /* Compute maximum encoding's size */ + if(max_encoded_len < (size_t)erval.encoded) + max_encoded_len = erval.encoded; + } + + /* + * Encode the TLV for the sequence itself. + */ + encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag, + cb, app_key); + if(encoding_size == -1) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + computed_size += encoding_size; + + if(!cb || list->count == 0) { + erval.encoded = computed_size; + _ASN_ENCODED_OK(erval); + } + + /* + * DER mandates dynamic sorting of the SET OF elements + * according to their encodings. Build an array of the + * encoded elements. + */ + encoded_els = (struct _el_buffer *)MALLOC( + list->count * sizeof(encoded_els[0])); + if(encoded_els == NULL) { + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + ASN_DEBUG("Encoding members of %s SET OF", td->name); + + /* + * Encode all members. + */ + for(edx = 0; edx < list->count; edx++) { + void *memb_ptr = list->array[edx]; + struct _el_buffer *encoded_el = &encoded_els[eels_count]; + + if(!memb_ptr) continue; + + /* + * Prepare space for encoding. + */ + encoded_el->buf = (uint8_t *)MALLOC(max_encoded_len); + if(encoded_el->buf) { + encoded_el->length = 0; + encoded_el->size = max_encoded_len; + } else { + for(edx--; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + return erval; + } + + /* + * Encode the member into the prepared space. + */ + erval = der_encoder(elm_type, memb_ptr, 0, elm->tag, + _el_addbytes, encoded_el); + if(erval.encoded == -1) { + for(; edx >= 0; edx--) + FREEMEM(encoded_els[edx].buf); + FREEMEM(encoded_els); + return erval; + } + encoding_size += erval.encoded; + eels_count++; + } + + /* + * Sort the encoded elements according to their encoding. + */ + qsort(encoded_els, eels_count, sizeof(encoded_els[0]), _el_buf_cmp); + + /* + * Report encoded elements to the application. + * Dispose of temporary sorted members table. + */ + ret = 0; + for(edx = 0; edx < eels_count; edx++) { + struct _el_buffer *encoded_el = &encoded_els[edx]; + /* Report encoded chunks to the application */ + if(ret == 0 + && cb(encoded_el->buf, encoded_el->length, app_key) < 0) + ret = -1; + FREEMEM(encoded_el->buf); + } + FREEMEM(encoded_els); + + if(ret || computed_size != (size_t)encoding_size) { + /* + * Standard callback failed, or + * encoded size is not equal to the computed size. + */ + erval.encoded = -1; + erval.failed_type = td; + erval.structure_ptr = ptr; + } else { + erval.encoded = computed_size; + } + + _ASN_ENCODED_OK(erval); +} + +#undef XER_ADVANCE +#define XER_ADVANCE(num_bytes) do { \ + size_t num = num_bytes; \ + buf_ptr = ((const char *)buf_ptr) + num;\ + size -= num; \ + consumed_myself += num; \ + } while(0) + +/* + * Decode the XER (XML) data. + */ +asn_dec_rval_t +SET_OF_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const char *opt_mname, + const void *buf_ptr, size_t size) { + /* + * Bring closer parts of structure description. + */ + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *element = td->elements; + const char *elm_tag; + const char *xml_tag = opt_mname ? opt_mname : td->xml_tag; + + /* + * ... and parts of the structure being constructed. + */ + void *st = *struct_ptr; /* Target structure. */ + asn_struct_ctx_t *ctx; /* Decoder context */ + + asn_dec_rval_t rval; /* Return value from a decoder */ + ssize_t consumed_myself = 0; /* Consumed bytes from ptr */ + + /* + * Create the target structure if it is not present already. + */ + if(st == 0) { + st = *struct_ptr = CALLOC(1, specs->struct_size); + if(st == 0) RETURN(RC_FAIL); + } + + /* Which tag is expected for the downstream */ + if(specs->as_XMLValueList) { + elm_tag = (specs->as_XMLValueList == 1) ? 0 : ""; + } else { + elm_tag = (*element->name) + ? element->name : element->type->xml_tag; + } + + /* + * Restore parsing context. + */ + ctx = (asn_struct_ctx_t *)((char *)st + specs->ctx_offset); + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + * Phase 2: Processing inner type. + */ + for(; ctx->phase <= 2;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + + /* + * Go inside the inner member of a set. + */ + if(ctx->phase == 2) { + asn_dec_rval_t tmprval; + + /* Invoke the inner type decoder, m.b. multiple times */ + ASN_DEBUG("XER/SET OF element [%s]", elm_tag); + tmprval = element->type->xer_decoder(opt_codec_ctx, + element->type, &ctx->ptr, elm_tag, + buf_ptr, size); + if(tmprval.code == RC_OK) { + asn_anonymous_set_ *list = _A_SET_FROM_VOID(st); + if(ASN_SET_ADD(list, ctx->ptr) != 0) + RETURN(RC_FAIL); + ctx->ptr = 0; + XER_ADVANCE(tmprval.consumed); + } else { + XER_ADVANCE(tmprval.consumed); + RETURN(tmprval.code); + } + ctx->phase = 1; /* Back to body processing */ + ASN_DEBUG("XER/SET OF phase => %d", ctx->phase); + /* Fall through */ + } + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, + buf_ptr, size, &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + case PXER_TEXT: /* Ignore free-standing text */ + XER_ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + ASN_DEBUG("XER/SET OF: tcv = %d, ph=%d t=%s", + tcv, ctx->phase, xml_tag); + switch(tcv) { + case XCT_CLOSING: + if(ctx->phase == 0) break; + ctx->phase = 0; + /* Fall through */ + case XCT_BOTH: + if(ctx->phase == 0) { + /* No more things to decode */ + XER_ADVANCE(ch_size); + ctx->phase = 3; /* Phase out */ + RETURN(RC_OK); + } + /* Fall through */ + case XCT_OPENING: + if(ctx->phase == 0) { + XER_ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + } + /* Fall through */ + case XCT_UNKNOWN_OP: + case XCT_UNKNOWN_BO: + + ASN_DEBUG("XER/SET OF: tcv=%d, ph=%d", tcv, ctx->phase); + if(ctx->phase == 1) { + /* + * Process a single possible member. + */ + ctx->phase = 2; + continue; + } + /* Fall through */ + default: + break; + } + + ASN_DEBUG("Unexpected XML tag in SET OF"); + break; + } + + ctx->phase = 3; /* "Phase out" on hard failure */ + RETURN(RC_FAIL); +} + + + +typedef struct xer_tmp_enc_s { + void *buffer; + size_t offset; + size_t size; +} xer_tmp_enc_t; +static int +SET_OF_encode_xer_callback(const void *buffer, size_t size, void *key) { + xer_tmp_enc_t *t = (xer_tmp_enc_t *)key; + if(t->offset + size >= t->size) { + size_t newsize = (t->size << 2) + size; + void *p = REALLOC(t->buffer, newsize); + if(!p) return -1; + t->buffer = p; + t->size = newsize; + } + memcpy((char *)t->buffer + t->offset, buffer, size); + t->offset += size; + return 0; +} +static int +SET_OF_xer_order(const void *aptr, const void *bptr) { + const xer_tmp_enc_t *a = (const xer_tmp_enc_t *)aptr; + const xer_tmp_enc_t *b = (const xer_tmp_enc_t *)bptr; + size_t minlen = a->offset; + int ret; + if(b->offset < minlen) minlen = b->offset; + /* Well-formed UTF-8 has this nice lexicographical property... */ + ret = memcmp(a->buffer, b->buffer, minlen); + if(ret != 0) return ret; + if(a->offset == b->offset) + return 0; + if(a->offset == minlen) + return -1; + return 1; +} + + +asn_enc_rval_t +SET_OF_encode_xer(asn_TYPE_descriptor_t *td, void *sptr, + int ilevel, enum xer_encoder_flags_e flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(sptr); + const char *mname = specs->as_XMLValueList + ? 0 : ((*elm->name) ? elm->name : elm->type->xml_tag); + size_t mlen = mname ? strlen(mname) : 0; + int xcan = (flags & XER_F_CANONICAL); + xer_tmp_enc_t *encs = 0; + size_t encs_count = 0; + void *original_app_key = app_key; + asn_app_consume_bytes_f *original_cb = cb; + int i; + + if(!sptr) _ASN_ENCODE_FAILED; + + if(xcan) { + encs = (xer_tmp_enc_t *)MALLOC(list->count * sizeof(encs[0])); + if(!encs) _ASN_ENCODE_FAILED; + cb = SET_OF_encode_xer_callback; + } + + er.encoded = 0; + + for(i = 0; i < list->count; i++) { + asn_enc_rval_t tmper; + + void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + if(encs) { + memset(&encs[encs_count], 0, sizeof(encs[0])); + app_key = &encs[encs_count]; + encs_count++; + } + + if(mname) { + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel); + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + } + + if(!xcan && specs->as_XMLValueList == 1) + _i_ASN_TEXT_INDENT(1, ilevel + 1); + tmper = elm->type->xer_encoder(elm->type, memb_ptr, + ilevel + (specs->as_XMLValueList != 2), + flags, cb, app_key); + if(tmper.encoded == -1) { + td = tmper.failed_type; + sptr = tmper.structure_ptr; + goto cb_failed; + } + if(tmper.encoded == 0 && specs->as_XMLValueList) { + const char *name = elm->type->xml_tag; + size_t len = strlen(name); + _ASN_CALLBACK3("<", 1, name, len, "/>", 2); + } + + if(mname) { + _ASN_CALLBACK3("", 1); + er.encoded += 5; + } + + er.encoded += (2 * mlen) + tmper.encoded; + } + + if(!xcan) _i_ASN_TEXT_INDENT(1, ilevel - 1); + + if(encs) { + xer_tmp_enc_t *enc = encs; + xer_tmp_enc_t *end = encs + encs_count; + ssize_t control_size = 0; + + cb = original_cb; + app_key = original_app_key; + qsort(encs, encs_count, sizeof(encs[0]), SET_OF_xer_order); + + for(; enc < end; enc++) { + _ASN_CALLBACK(enc->buffer, enc->offset); + FREEMEM(enc->buffer); + enc->buffer = 0; + control_size += enc->offset; + } + assert(control_size == er.encoded); + } + + goto cleanup; +cb_failed: + er.encoded = -1; + er.failed_type = td; + er.structure_ptr = sptr; +cleanup: + if(encs) { + while(encs_count-- > 0) { + if(encs[encs_count].buffer) + FREEMEM(encs[encs_count].buffer); + } + FREEMEM(encs); + } + _ASN_ENCODED_OK(er); +} + +int +SET_OF_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int ret; + int i; + + if(!sptr) return (cb("", 8, app_key) < 0) ? -1 : 0; + + /* Dump preamble */ + if(cb(td->name, strlen(td->name), app_key) < 0 + || cb(" ::= {", 6, app_key) < 0) + return -1; + + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + if(!memb_ptr) continue; + + _i_INDENT(1); + + ret = elm->type->print_struct(elm->type, memb_ptr, + ilevel + 1, cb, app_key); + if(ret) return ret; + } + + ilevel--; + _i_INDENT(1); + + return (cb("}", 1, app_key) < 0) ? -1 : 0; +} + +void +SET_OF_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) { + if(td && ptr) { + asn_TYPE_member_t *elm = td->elements; + asn_anonymous_set_ *list = _A_SET_FROM_VOID(ptr); + int i; + + /* + * Could not use set_of_empty() because of (*free) + * incompatibility. + */ + for(i = 0; i < list->count; i++) { + void *memb_ptr = list->array[i]; + if(memb_ptr) + ASN_STRUCT_FREE(*elm->type, memb_ptr); + } + list->count = 0; /* No meaningful elements left */ + + asn_set_empty(list); /* Remove (list->array) */ + + if(!contents_only) { + FREEMEM(ptr); + } + } +} + +int +SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr, + asn_app_constraint_failed_f *ctfailcb, void *app_key) { + asn_TYPE_member_t *elm = td->elements; + asn_constr_check_f *constr; + const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr); + int i; + + if(!sptr) { + _ASN_CTFAIL(app_key, td, + "%s: value not given (%s:%d)", + td->name, __FILE__, __LINE__); + return -1; + } + + constr = elm->memb_constraints; + if(!constr) constr = elm->type->check_constraints; + + /* + * Iterate over the members of an array. + * Validate each in turn, until one fails. + */ + for(i = 0; i < list->count; i++) { + const void *memb_ptr = list->array[i]; + int ret; + + if(!memb_ptr) continue; + + ret = constr(elm->type, memb_ptr, ctfailcb, app_key); + if(ret) return ret; + } + + /* + * Cannot inherit it eralier: + * need to make sure we get the updated version. + */ + if(!elm->memb_constraints) + elm->memb_constraints = elm->type->check_constraints; + + return 0; +} + +asn_dec_rval_t +SET_OF_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) { + asn_dec_rval_t rv; + asn_SET_OF_specifics_t *specs = (asn_SET_OF_specifics_t *)td->specifics; + asn_TYPE_member_t *elm = td->elements; /* Single one */ + void *st = *sptr; + asn_anonymous_set_ *list; + asn_per_constraint_t *ct; + int repeat = 0; + ssize_t nelems; + + if(_ASN_STACK_OVERFLOW_CHECK(opt_codec_ctx)) + _ASN_DECODE_FAILED; + + /* + * Create the target structure if it is not present already. + */ + if(!st) { + st = *sptr = CALLOC(1, specs->struct_size); + if(!st) _ASN_DECODE_FAILED; + } + list = _A_SET_FROM_VOID(st); + + /* Figure out which constraints to use */ + if(constraints) ct = &constraints->size; + else if(td->per_constraints) ct = &td->per_constraints->size; + else ct = 0; + + if(ct && ct->flags & APC_EXTENSIBLE) { + int value = per_get_few_bits(pd, 1); + if(value < 0) _ASN_DECODE_STARVED; + if(value) ct = 0; /* Not restricted! */ + } + + if(ct && ct->effective_bits >= 0) { + /* X.691, #19.5: No length determinant */ + nelems = per_get_few_bits(pd, ct->effective_bits); + ASN_DEBUG("Preparing to fetch %ld+%ld elements from %s", + (long)nelems, ct->lower_bound, td->name); + if(nelems < 0) _ASN_DECODE_STARVED; + nelems += ct->lower_bound; + } else { + nelems = -1; + } + + do { + int i; + if(nelems < 0) { + nelems = uper_get_length(pd, + ct ? ct->effective_bits : -1, &repeat); + ASN_DEBUG("Got to decode %d elements (eff %d)", + (int)nelems, ct ? ct->effective_bits : -1); + if(nelems < 0) _ASN_DECODE_STARVED; + } + + for(i = 0; i < nelems; i++) { + void *ptr = 0; + ASN_DEBUG("SET OF %s decoding", elm->type->name); + rv = elm->type->uper_decoder(opt_codec_ctx, elm->type, + elm->per_constraints, &ptr, pd); + ASN_DEBUG("%s SET OF %s decoded %d, %p", + td->name, elm->type->name, rv.code, ptr); + if(rv.code == RC_OK) { + if(ASN_SET_ADD(list, ptr) == 0) + continue; + ASN_DEBUG("Failed to add element into %s", + td->name); + /* Fall through */ + rv.code = RC_FAIL; + } else { + ASN_DEBUG("Failed decoding %s of %s (SET OF)", + elm->type->name, td->name); + } + if(ptr) ASN_STRUCT_FREE(*elm->type, ptr); + return rv; + } + + nelems = -1; /* Allow uper_get_length() */ + } while(repeat); + + ASN_DEBUG("Decoded %s as SET OF", td->name); + + rv.code = RC_OK; + rv.consumed = 0; + return rv; +} + diff --git a/libs/smux/constr_TYPE.c b/libs/smux/constr_TYPE.c new file mode 100644 index 00000000..4bc88d44 --- /dev/null +++ b/libs/smux/constr_TYPE.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Version of the ASN.1 infrastructure shipped with compiler. + */ +int get_asn1c_environment_version() { return ASN1C_ENVIRONMENT_VERSION; } + +static asn_app_consume_bytes_f _print2fp; + +/* + * Return the outmost tag of the type. + */ +ber_tlv_tag_t +asn_TYPE_outmost_tag(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag) { + + if(tag_mode) + return tag; + + if(type_descriptor->tags_count) + return type_descriptor->tags[0]; + + return type_descriptor->outmost_tag(type_descriptor, struct_ptr, 0, 0); +} + +/* + * Print the target language's structure in human readable form. + */ +int +asn_fprint(FILE *stream, asn_TYPE_descriptor_t *td, const void *struct_ptr) { + if(!stream) stream = stdout; + if(!td || !struct_ptr) { + errno = EINVAL; + return -1; + } + + /* Invoke type-specific printer */ + if(td->print_struct(td, struct_ptr, 1, _print2fp, stream)) + return -1; + + /* Terminate the output */ + if(_print2fp("\n", 1, stream)) + return -1; + + return fflush(stream); +} + +/* Dump the data into the specified stdio stream */ +static int +_print2fp(const void *buffer, size_t size, void *app_key) { + FILE *stream = (FILE *)app_key; + + if(fwrite(buffer, 1, size, stream) != size) + return -1; + + return 0; +} + + +/* + * Some compilers do not support variable args macros. + * This function is a replacement of ASN_DEBUG() macro. + */ +void ASN_DEBUG_f(const char *fmt, ...); +void ASN_DEBUG_f(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} diff --git a/libs/smux/constraints.c b/libs/smux/constraints.c new file mode 100644 index 00000000..1bdda73e --- /dev/null +++ b/libs/smux/constraints.c @@ -0,0 +1,93 @@ +#include "asn_internal.h" +#include "constraints.h" + +int +asn_generic_no_constraint(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) { + + (void)type_descriptor; /* Unused argument */ + (void)struct_ptr; /* Unused argument */ + (void)cb; /* Unused argument */ + (void)key; /* Unused argument */ + + /* Nothing to check */ + return 0; +} + +int +asn_generic_unknown_constraint(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) { + + (void)type_descriptor; /* Unused argument */ + (void)struct_ptr; /* Unused argument */ + (void)cb; /* Unused argument */ + (void)key; /* Unused argument */ + + /* Unknown how to check */ + return 0; +} + +struct errbufDesc { + asn_TYPE_descriptor_t *failed_type; + const void *failed_struct_ptr; + char *errbuf; + size_t errlen; +}; + +static void +_asn_i_ctfailcb(void *key, asn_TYPE_descriptor_t *td, const void *sptr, const char *fmt, ...) { + struct errbufDesc *arg = key; + va_list ap; + ssize_t vlen; + ssize_t maxlen; + + arg->failed_type = td; + arg->failed_struct_ptr = sptr; + + maxlen = arg->errlen; + if(maxlen <= 0) + return; + + va_start(ap, fmt); + vlen = vsnprintf(arg->errbuf, maxlen, fmt, ap); + va_end(ap); + if(vlen >= maxlen) { + arg->errbuf[maxlen-1] = '\0'; /* Ensuring libc correctness */ + arg->errlen = maxlen - 1; /* Not counting termination */ + return; + } else if(vlen >= 0) { + arg->errbuf[vlen] = '\0'; /* Ensuring libc correctness */ + arg->errlen = vlen; /* Not counting termination */ + } else { + /* + * The libc on this system is broken. + */ + vlen = sizeof("") - 1; + maxlen--; + arg->errlen = vlen < maxlen ? vlen : maxlen; + memcpy(arg->errbuf, "", arg->errlen); + arg->errbuf[arg->errlen] = 0; + } + + return; +} + +int +asn_check_constraints(asn_TYPE_descriptor_t *type_descriptor, + const void *struct_ptr, char *errbuf, size_t *errlen) { + struct errbufDesc arg; + int ret; + + arg.failed_type = 0; + arg.failed_struct_ptr = 0; + arg.errbuf = errbuf; + arg.errlen = errlen ? *errlen : 0; + + ret = type_descriptor->check_constraints(type_descriptor, + struct_ptr, _asn_i_ctfailcb, &arg); + if(ret == -1 && errlen) + *errlen = arg.errlen; + + return ret; +} + diff --git a/libs/smux/der_encoder.c b/libs/smux/der_encoder.c new file mode 100644 index 00000000..6c859e1b --- /dev/null +++ b/libs/smux/der_encoder.c @@ -0,0 +1,199 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +static ssize_t der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len, + asn_app_consume_bytes_f *cb, void *app_key, int constructed); + +/* + * The DER encoder of any type. + */ +asn_enc_rval_t +der_encode(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr, + asn_app_consume_bytes_f *consume_bytes, void *app_key) { + + ASN_DEBUG("DER encoder invoked for %s", + type_descriptor->name); + + /* + * Invoke type-specific encoder. + */ + return type_descriptor->der_encoder(type_descriptor, + struct_ptr, /* Pointer to the destination structure */ + 0, 0, + consume_bytes, app_key); +} + +/* + * Argument type and callback necessary for der_encode_to_buffer(). + */ +typedef struct enc_to_buf_arg { + void *buffer; + size_t left; +} enc_to_buf_arg; +static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) { + enc_to_buf_arg *arg = (enc_to_buf_arg *)key; + + if(arg->left < size) + return -1; /* Data exceeds the available buffer size */ + + memcpy(arg->buffer, buffer, size); + arg->buffer = ((char *)arg->buffer) + size; + arg->left -= size; + + return 0; +} + +/* + * A variant of the der_encode() which encodes the data into the provided buffer + */ +asn_enc_rval_t +der_encode_to_buffer(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr, + void *buffer, size_t buffer_size) { + enc_to_buf_arg arg; + asn_enc_rval_t ec; + + arg.buffer = buffer; + arg.left = buffer_size; + + ec = type_descriptor->der_encoder(type_descriptor, + struct_ptr, /* Pointer to the destination structure */ + 0, 0, encode_to_buffer_cb, &arg); + if(ec.encoded != -1) { + assert(ec.encoded == (ssize_t)(buffer_size - arg.left)); + /* Return the encoded contents size */ + } + return ec; +} + + +/* + * Write out leading TL[v] sequence according to the type definition. + */ +ssize_t +der_write_tags(asn_TYPE_descriptor_t *sd, + size_t struct_length, + int tag_mode, int last_tag_form, + ber_tlv_tag_t tag, /* EXPLICIT or IMPLICIT tag */ + asn_app_consume_bytes_f *cb, + void *app_key) { + ber_tlv_tag_t *tags; /* Copy of tags stream */ + int tags_count; /* Number of tags */ + size_t overall_length; + ssize_t *lens; + int i; + + ASN_DEBUG("Writing tags (%s, tm=%d, tc=%d, tag=%s, mtc=%d)", + sd->name, tag_mode, sd->tags_count, + ber_tlv_tag_string(tag), + tag_mode + ?(sd->tags_count+1 + -((tag_mode == -1) && sd->tags_count)) + :sd->tags_count + ); + + if(tag_mode) { + /* + * Instead of doing shaman dance like we do in ber_check_tags(), + * allocate a small array on the stack + * and initialize it appropriately. + */ + int stag_offset; + tags = (ber_tlv_tag_t *)alloca((sd->tags_count + 1) * sizeof(ber_tlv_tag_t)); + if(!tags) { /* Can fail on !x86 */ + errno = ENOMEM; + return -1; + } + tags_count = sd->tags_count + + 1 /* EXPLICIT or IMPLICIT tag is given */ + - ((tag_mode == -1) && sd->tags_count); + /* Copy tags over */ + tags[0] = tag; + stag_offset = -1 + ((tag_mode == -1) && sd->tags_count); + for(i = 1; i < tags_count; i++) + tags[i] = sd->tags[i + stag_offset]; + } else { + tags = sd->tags; + tags_count = sd->tags_count; + } + + /* No tags to write */ + if(tags_count == 0) + return 0; + + lens = (ssize_t *)alloca(tags_count * sizeof(lens[0])); + if(!lens) { + errno = ENOMEM; + return -1; + } + + /* + * Array of tags is initialized. + * Now, compute the size of the TLV pairs, from right to left. + */ + overall_length = struct_length; + for(i = tags_count - 1; i >= 0; --i) { + lens[i] = der_write_TL(tags[i], overall_length, 0, 0, 0); + if(lens[i] == -1) return -1; + overall_length += lens[i]; + lens[i] = overall_length - lens[i]; + } + + if(!cb) return overall_length - struct_length; + + ASN_DEBUG("%s %s TL sequence (%d elements)", + cb?"Encoding":"Estimating", sd->name, tags_count); + + /* + * Encode the TL sequence for real. + */ + for(i = 0; i < tags_count; i++) { + ssize_t len; + int _constr; + + /* Check if this tag happens to be constructed */ + _constr = (last_tag_form || i < (tags_count - 1)); + + len = der_write_TL(tags[i], lens[i], cb, app_key, _constr); + if(len == -1) return -1; + } + + return overall_length - struct_length; +} + +static ssize_t +der_write_TL(ber_tlv_tag_t tag, ber_tlv_len_t len, + asn_app_consume_bytes_f *cb, void *app_key, + int constructed) { + uint8_t buf[32]; + size_t size = 0; + int buf_size = cb?sizeof(buf):0; + ssize_t tmp; + + /* Serialize tag (T from TLV) into possibly zero-length buffer */ + tmp = ber_tlv_tag_serialize(tag, buf, buf_size); + if(tmp == -1 || tmp > (ssize_t)sizeof(buf)) return -1; + size += tmp; + + /* Serialize length (L from TLV) into possibly zero-length buffer */ + tmp = der_tlv_length_serialize(len, buf+size, buf_size?buf_size-size:0); + if(tmp == -1) return -1; + size += tmp; + + if(size > sizeof(buf)) + return -1; + + /* + * If callback is specified, invoke it, and check its return value. + */ + if(cb) { + if(constructed) *buf |= 0x20; + if(cb(buf, size, app_key) < 0) + return -1; + } + + return size; +} diff --git a/libs/smux/include/stg/ANY.h b/libs/smux/include/stg/ANY.h new file mode 100644 index 00000000..b7d92fa9 --- /dev/null +++ b/libs/smux/include/stg/ANY.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_TYPE_ANY_H +#define ASN_TYPE_ANY_H + +#include /* Implemented via OCTET STRING type */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ANY { + uint8_t *buf; /* BER-encoded ANY contents */ + int size; /* Size of the above buffer */ + + asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */ +} ANY_t; + +extern asn_TYPE_descriptor_t asn_DEF_ANY; + +asn_struct_free_f ANY_free; +asn_struct_print_f ANY_print; +ber_type_decoder_f ANY_decode_ber; +der_type_encoder_f ANY_encode_der; +xer_type_encoder_f ANY_encode_xer; + +/****************************** + * Handy conversion routines. * + ******************************/ + +/* Convert another ASN.1 type into the ANY. This implies DER encoding. */ +int ANY_fromType(ANY_t *, asn_TYPE_descriptor_t *td, void *struct_ptr); +ANY_t *ANY_new_fromType(asn_TYPE_descriptor_t *td, void *struct_ptr); + +/* Convert the contents of the ANY type into the specified type. */ +int ANY_to_type(ANY_t *, asn_TYPE_descriptor_t *td, void **struct_ptr); + +#define ANY_fromBuf(s, buf, size) OCTET_STRING_fromBuf((s), (buf), (size)) +#define ANY_new_fromBuf(buf, size) OCTET_STRING_new_fromBuf( \ + &asn_DEF_ANY, (buf), (size)) + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_TYPE_ANY_H */ diff --git a/libs/smux/include/stg/ApplicationSyntax.h b/libs/smux/include/stg/ApplicationSyntax.h new file mode 100644 index 00000000..90a87076 --- /dev/null +++ b/libs/smux/include/stg/ApplicationSyntax.h @@ -0,0 +1,58 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _ApplicationSyntax_H_ +#define _ApplicationSyntax_H_ + + +#include + +/* Including external dependencies */ +#include "NetworkAddress.h" +#include "Counter.h" +#include "Gauge.h" +#include "TimeTicks.h" +#include "Opaque.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ApplicationSyntax_PR { + ApplicationSyntax_PR_NOTHING, /* No components present */ + ApplicationSyntax_PR_address, + ApplicationSyntax_PR_counter, + ApplicationSyntax_PR_gauge, + ApplicationSyntax_PR_ticks, + ApplicationSyntax_PR_arbitrary +} ApplicationSyntax_PR; + +/* ApplicationSyntax */ +typedef struct ApplicationSyntax { + ApplicationSyntax_PR present; + union ApplicationSyntax_u { + NetworkAddress_t address; + Counter_t counter; + Gauge_t gauge; + TimeTicks_t ticks; + Opaque_t arbitrary; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ApplicationSyntax_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ApplicationSyntax; + +#ifdef __cplusplus +} +#endif + +#endif /* _ApplicationSyntax_H_ */ diff --git a/libs/smux/include/stg/AtEntry.h b/libs/smux/include/stg/AtEntry.h new file mode 100644 index 00000000..a0aba105 --- /dev/null +++ b/libs/smux/include/stg/AtEntry.h @@ -0,0 +1,41 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _AtEntry_H_ +#define _AtEntry_H_ + + +#include + +/* Including external dependencies */ +#include +#include "PhysAddress.h" +#include "NetworkAddress.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* AtEntry */ +typedef struct AtEntry { + INTEGER_t atIfIndex; + PhysAddress_t atPhysAddress; + NetworkAddress_t atNetAddress; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} AtEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_AtEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _AtEntry_H_ */ diff --git a/libs/smux/include/stg/BIT_STRING.h b/libs/smux/include/stg/BIT_STRING.h new file mode 100644 index 00000000..732e878b --- /dev/null +++ b/libs/smux/include/stg/BIT_STRING.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BIT_STRING_H_ +#define _BIT_STRING_H_ + +#include /* Some help from OCTET STRING */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct BIT_STRING_s { + uint8_t *buf; /* BIT STRING body */ + int size; /* Size of the above buffer */ + + int bits_unused;/* Unused trailing bits in the last octet (0..7) */ + + asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */ +} BIT_STRING_t; + +extern asn_TYPE_descriptor_t asn_DEF_BIT_STRING; + +asn_struct_print_f BIT_STRING_print; /* Human-readable output */ +asn_constr_check_f BIT_STRING_constraint; +xer_type_encoder_f BIT_STRING_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _BIT_STRING_H_ */ diff --git a/libs/smux/include/stg/BOOLEAN.h b/libs/smux/include/stg/BOOLEAN.h new file mode 100644 index 00000000..217d0f16 --- /dev/null +++ b/libs/smux/include/stg/BOOLEAN.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BOOLEAN_H_ +#define _BOOLEAN_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The underlying integer may contain various values, but everything + * non-zero is capped to 0xff by the DER encoder. The BER decoder may + * yield non-zero values different from 1, beware. + */ +typedef int BOOLEAN_t; + +extern asn_TYPE_descriptor_t asn_DEF_BOOLEAN; + +asn_struct_free_f BOOLEAN_free; +asn_struct_print_f BOOLEAN_print; +ber_type_decoder_f BOOLEAN_decode_ber; +der_type_encoder_f BOOLEAN_encode_der; +xer_type_decoder_f BOOLEAN_decode_xer; +xer_type_encoder_f BOOLEAN_encode_xer; +per_type_decoder_f BOOLEAN_decode_uper; +per_type_encoder_f BOOLEAN_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _BOOLEAN_H_ */ diff --git a/libs/smux/include/stg/ClosePDU.h b/libs/smux/include/stg/ClosePDU.h new file mode 100644 index 00000000..a3d1e7a9 --- /dev/null +++ b/libs/smux/include/stg/ClosePDU.h @@ -0,0 +1,48 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _ClosePDU_H_ +#define _ClosePDU_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ClosePDU { + ClosePDU_goingDown = 0, + ClosePDU_unsupportedVersion = 1, + ClosePDU_packetFormat = 2, + ClosePDU_protocolError = 3, + ClosePDU_internalError = 4, + ClosePDU_authenticationFailure = 5 +} e_ClosePDU; + +/* ClosePDU */ +typedef INTEGER_t ClosePDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ClosePDU; +asn_struct_free_f ClosePDU_free; +asn_struct_print_f ClosePDU_print; +asn_constr_check_f ClosePDU_constraint; +ber_type_decoder_f ClosePDU_decode_ber; +der_type_encoder_f ClosePDU_encode_der; +xer_type_decoder_f ClosePDU_decode_xer; +xer_type_encoder_f ClosePDU_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _ClosePDU_H_ */ diff --git a/libs/smux/include/stg/Counter.h b/libs/smux/include/stg/Counter.h new file mode 100644 index 00000000..3c770ada --- /dev/null +++ b/libs/smux/include/stg/Counter.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _Counter_H_ +#define _Counter_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Counter */ +typedef INTEGER_t Counter_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_Counter; +asn_struct_free_f Counter_free; +asn_struct_print_f Counter_print; +asn_constr_check_f Counter_constraint; +ber_type_decoder_f Counter_decode_ber; +der_type_encoder_f Counter_encode_der; +xer_type_decoder_f Counter_decode_xer; +xer_type_encoder_f Counter_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _Counter_H_ */ diff --git a/libs/smux/include/stg/DisplayString.h b/libs/smux/include/stg/DisplayString.h new file mode 100644 index 00000000..ac6862c2 --- /dev/null +++ b/libs/smux/include/stg/DisplayString.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _DisplayString_H_ +#define _DisplayString_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* DisplayString */ +typedef OCTET_STRING_t DisplayString_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_DisplayString; +asn_struct_free_f DisplayString_free; +asn_struct_print_f DisplayString_print; +asn_constr_check_f DisplayString_constraint; +ber_type_decoder_f DisplayString_decode_ber; +der_type_encoder_f DisplayString_encode_der; +xer_type_decoder_f DisplayString_decode_xer; +xer_type_encoder_f DisplayString_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _DisplayString_H_ */ diff --git a/libs/smux/include/stg/EgpNeighEntry.h b/libs/smux/include/stg/EgpNeighEntry.h new file mode 100644 index 00000000..79d3eedd --- /dev/null +++ b/libs/smux/include/stg/EgpNeighEntry.h @@ -0,0 +1,53 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _EgpNeighEntry_H_ +#define _EgpNeighEntry_H_ + + +#include + +/* Including external dependencies */ +#include +#include "IpAddress.h" +#include "Counter.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* EgpNeighEntry */ +typedef struct EgpNeighEntry { + INTEGER_t egpNeighState; + IpAddress_t egpNeighAddr; + INTEGER_t egpNeighAs; + Counter_t egpNeighInMsgs; + Counter_t egpNeighInErrs; + Counter_t egpNeighOutMsgs; + Counter_t egpNeighOutErrs; + Counter_t egpNeighInErrMsgs; + Counter_t egpNeighOutErrMsgs; + Counter_t egpNeighStateUps; + Counter_t egpNeighStateDowns; + INTEGER_t egpNeighIntervalHello; + INTEGER_t egpNeighIntervalPoll; + INTEGER_t egpNeighMode; + INTEGER_t egpNeighEventTrigger; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} EgpNeighEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_EgpNeighEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _EgpNeighEntry_H_ */ diff --git a/libs/smux/include/stg/Gauge.h b/libs/smux/include/stg/Gauge.h new file mode 100644 index 00000000..f3e17c5e --- /dev/null +++ b/libs/smux/include/stg/Gauge.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _Gauge_H_ +#define _Gauge_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Gauge */ +typedef INTEGER_t Gauge_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_Gauge; +asn_struct_free_f Gauge_free; +asn_struct_print_f Gauge_print; +asn_constr_check_f Gauge_constraint; +ber_type_decoder_f Gauge_decode_ber; +der_type_encoder_f Gauge_encode_der; +xer_type_decoder_f Gauge_decode_xer; +xer_type_encoder_f Gauge_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _Gauge_H_ */ diff --git a/libs/smux/include/stg/GetNextRequest-PDU.h b/libs/smux/include/stg/GetNextRequest-PDU.h new file mode 100644 index 00000000..f9298ec6 --- /dev/null +++ b/libs/smux/include/stg/GetNextRequest-PDU.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _GetNextRequest_PDU_H_ +#define _GetNextRequest_PDU_H_ + + +#include + +/* Including external dependencies */ +#include "PDU.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* GetNextRequest-PDU */ +typedef PDU_t GetNextRequest_PDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_GetNextRequest_PDU; +asn_struct_free_f GetNextRequest_PDU_free; +asn_struct_print_f GetNextRequest_PDU_print; +asn_constr_check_f GetNextRequest_PDU_constraint; +ber_type_decoder_f GetNextRequest_PDU_decode_ber; +der_type_encoder_f GetNextRequest_PDU_encode_der; +xer_type_decoder_f GetNextRequest_PDU_decode_xer; +xer_type_encoder_f GetNextRequest_PDU_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _GetNextRequest_PDU_H_ */ diff --git a/libs/smux/include/stg/GetRequest-PDU.h b/libs/smux/include/stg/GetRequest-PDU.h new file mode 100644 index 00000000..9449451f --- /dev/null +++ b/libs/smux/include/stg/GetRequest-PDU.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _GetRequest_PDU_H_ +#define _GetRequest_PDU_H_ + + +#include + +/* Including external dependencies */ +#include "PDU.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* GetRequest-PDU */ +typedef PDU_t GetRequest_PDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_GetRequest_PDU; +asn_struct_free_f GetRequest_PDU_free; +asn_struct_print_f GetRequest_PDU_print; +asn_constr_check_f GetRequest_PDU_constraint; +ber_type_decoder_f GetRequest_PDU_decode_ber; +der_type_encoder_f GetRequest_PDU_encode_der; +xer_type_decoder_f GetRequest_PDU_decode_xer; +xer_type_encoder_f GetRequest_PDU_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _GetRequest_PDU_H_ */ diff --git a/libs/smux/include/stg/GetResponse-PDU.h b/libs/smux/include/stg/GetResponse-PDU.h new file mode 100644 index 00000000..12e3fba1 --- /dev/null +++ b/libs/smux/include/stg/GetResponse-PDU.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _GetResponse_PDU_H_ +#define _GetResponse_PDU_H_ + + +#include + +/* Including external dependencies */ +#include "PDU.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* GetResponse-PDU */ +typedef PDU_t GetResponse_PDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_GetResponse_PDU; +asn_struct_free_f GetResponse_PDU_free; +asn_struct_print_f GetResponse_PDU_print; +asn_constr_check_f GetResponse_PDU_constraint; +ber_type_decoder_f GetResponse_PDU_decode_ber; +der_type_encoder_f GetResponse_PDU_encode_der; +xer_type_decoder_f GetResponse_PDU_decode_xer; +xer_type_encoder_f GetResponse_PDU_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _GetResponse_PDU_H_ */ diff --git a/libs/smux/include/stg/INTEGER.h b/libs/smux/include/stg/INTEGER.h new file mode 100644 index 00000000..62832b12 --- /dev/null +++ b/libs/smux/include/stg/INTEGER.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _INTEGER_H_ +#define _INTEGER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ASN__PRIMITIVE_TYPE_t INTEGER_t; + +extern asn_TYPE_descriptor_t asn_DEF_INTEGER; + +/* Map with to integer value association */ +typedef struct asn_INTEGER_enum_map_s { + long nat_value; /* associated native integer value */ + size_t enum_len; /* strlen("tag") */ + const char *enum_name; /* "tag" */ +} asn_INTEGER_enum_map_t; + +/* This type describes an enumeration for INTEGER and ENUMERATED types */ +typedef struct asn_INTEGER_specifics_s { + asn_INTEGER_enum_map_t *value2enum; /* N -> "tag"; sorted by N */ + unsigned int *enum2value; /* "tag" => N; sorted by tag */ + int map_count; /* Elements in either map */ + int extension; /* This map is extensible */ + int strict_enumeration; /* Enumeration set is fixed */ +} asn_INTEGER_specifics_t; + +asn_struct_print_f INTEGER_print; +ber_type_decoder_f INTEGER_decode_ber; +der_type_encoder_f INTEGER_encode_der; +xer_type_decoder_f INTEGER_decode_xer; +xer_type_encoder_f INTEGER_encode_xer; +per_type_decoder_f INTEGER_decode_uper; +per_type_encoder_f INTEGER_encode_uper; + +/*********************************** + * Some handy conversion routines. * + ***********************************/ + +/* + * Returns 0 if it was possible to convert, -1 otherwise. + * -1/EINVAL: Mandatory argument missing + * -1/ERANGE: Value encoded is out of range for long representation + * -1/ENOMEM: Memory allocation failed (in asn_long2INTEGER()). + */ +int asn_INTEGER2long(const INTEGER_t *i, long *l); +int asn_long2INTEGER(INTEGER_t *i, long l); + +/* + * Convert the integer value into the corresponding enumeration map entry. + */ +const asn_INTEGER_enum_map_t *INTEGER_map_value2enum(asn_INTEGER_specifics_t *specs, long value); + +#ifdef __cplusplus +} +#endif + +#endif /* _INTEGER_H_ */ diff --git a/libs/smux/include/stg/IfEntry.h b/libs/smux/include/stg/IfEntry.h new file mode 100644 index 00000000..eb30717b --- /dev/null +++ b/libs/smux/include/stg/IfEntry.h @@ -0,0 +1,64 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _IfEntry_H_ +#define _IfEntry_H_ + + +#include + +/* Including external dependencies */ +#include +#include "DisplayString.h" +#include "Gauge.h" +#include "PhysAddress.h" +#include "TimeTicks.h" +#include "Counter.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IfEntry */ +typedef struct IfEntry { + INTEGER_t ifIndex; + DisplayString_t ifDescr; + INTEGER_t ifType; + INTEGER_t ifMtu; + Gauge_t ifSpeed; + PhysAddress_t ifPhysAddress; + INTEGER_t ifAdminStatus; + INTEGER_t ifOperStatus; + TimeTicks_t ifLastChange; + Counter_t ifInOctets; + Counter_t ifInUcastPkts; + Counter_t ifInNUcastPkts; + Counter_t ifInDiscards; + Counter_t ifInErrors; + Counter_t ifInUnknownProtos; + Counter_t ifOutOctets; + Counter_t ifOutUcastPkts; + Counter_t ifOutNUcastPkts; + Counter_t ifOutDiscards; + Counter_t ifOutErrors; + Gauge_t ifOutQLen; + OBJECT_IDENTIFIER_t ifSpecific; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} IfEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_IfEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _IfEntry_H_ */ diff --git a/libs/smux/include/stg/IpAddrEntry.h b/libs/smux/include/stg/IpAddrEntry.h new file mode 100644 index 00000000..9e36f32a --- /dev/null +++ b/libs/smux/include/stg/IpAddrEntry.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _IpAddrEntry_H_ +#define _IpAddrEntry_H_ + + +#include + +/* Including external dependencies */ +#include "IpAddress.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IpAddrEntry */ +typedef struct IpAddrEntry { + IpAddress_t ipAdEntAddr; + INTEGER_t ipAdEntIfIndex; + IpAddress_t ipAdEntNetMask; + INTEGER_t ipAdEntBcastAddr; + long ipAdEntReasmMaxSize; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} IpAddrEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_IpAddrEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _IpAddrEntry_H_ */ diff --git a/libs/smux/include/stg/IpAddress.h b/libs/smux/include/stg/IpAddress.h new file mode 100644 index 00000000..06c1d4a3 --- /dev/null +++ b/libs/smux/include/stg/IpAddress.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _IpAddress_H_ +#define _IpAddress_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IpAddress */ +typedef OCTET_STRING_t IpAddress_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_IpAddress; +asn_struct_free_f IpAddress_free; +asn_struct_print_f IpAddress_print; +asn_constr_check_f IpAddress_constraint; +ber_type_decoder_f IpAddress_decode_ber; +der_type_encoder_f IpAddress_encode_der; +xer_type_decoder_f IpAddress_decode_xer; +xer_type_encoder_f IpAddress_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _IpAddress_H_ */ diff --git a/libs/smux/include/stg/IpNetToMediaEntry.h b/libs/smux/include/stg/IpNetToMediaEntry.h new file mode 100644 index 00000000..1eb8124f --- /dev/null +++ b/libs/smux/include/stg/IpNetToMediaEntry.h @@ -0,0 +1,42 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _IpNetToMediaEntry_H_ +#define _IpNetToMediaEntry_H_ + + +#include + +/* Including external dependencies */ +#include +#include "PhysAddress.h" +#include "IpAddress.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IpNetToMediaEntry */ +typedef struct IpNetToMediaEntry { + INTEGER_t ipNetToMediaIfIndex; + PhysAddress_t ipNetToMediaPhysAddress; + IpAddress_t ipNetToMediaNetAddress; + INTEGER_t ipNetToMediaType; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} IpNetToMediaEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_IpNetToMediaEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _IpNetToMediaEntry_H_ */ diff --git a/libs/smux/include/stg/IpRouteEntry.h b/libs/smux/include/stg/IpRouteEntry.h new file mode 100644 index 00000000..5651a8fc --- /dev/null +++ b/libs/smux/include/stg/IpRouteEntry.h @@ -0,0 +1,51 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _IpRouteEntry_H_ +#define _IpRouteEntry_H_ + + +#include + +/* Including external dependencies */ +#include "IpAddress.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* IpRouteEntry */ +typedef struct IpRouteEntry { + IpAddress_t ipRouteDest; + INTEGER_t ipRouteIfIndex; + INTEGER_t ipRouteMetric1; + INTEGER_t ipRouteMetric2; + INTEGER_t ipRouteMetric3; + INTEGER_t ipRouteMetric4; + IpAddress_t ipRouteNextHop; + INTEGER_t ipRouteType; + INTEGER_t ipRouteProto; + INTEGER_t ipRouteAge; + IpAddress_t ipRouteMask; + INTEGER_t ipRouteMetric5; + OBJECT_IDENTIFIER_t ipRouteInfo; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} IpRouteEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_IpRouteEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _IpRouteEntry_H_ */ diff --git a/libs/smux/include/stg/Message.h b/libs/smux/include/stg/Message.h new file mode 100644 index 00000000..2621d73c --- /dev/null +++ b/libs/smux/include/stg/Message.h @@ -0,0 +1,46 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _Message_H_ +#define _Message_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum Message__version { + Message__version_version_1 = 0 +} e_Message__version; + +/* Message */ +typedef struct Message { + INTEGER_t version; + OCTET_STRING_t community; + ANY_t data; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} Message_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_Message; + +#ifdef __cplusplus +} +#endif + +#endif /* _Message_H_ */ diff --git a/libs/smux/include/stg/NULL.h b/libs/smux/include/stg/NULL.h new file mode 100644 index 00000000..131e7759 --- /dev/null +++ b/libs/smux/include/stg/NULL.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_TYPE_NULL_H +#define ASN_TYPE_NULL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The value of the NULL type is meaningless: see BOOLEAN if you want to + * carry true/false semantics. + */ +typedef int NULL_t; + +extern asn_TYPE_descriptor_t asn_DEF_NULL; + +asn_struct_print_f NULL_print; +der_type_encoder_f NULL_encode_der; +xer_type_decoder_f NULL_decode_xer; +xer_type_encoder_f NULL_encode_xer; +per_type_decoder_f NULL_decode_uper; +per_type_encoder_f NULL_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* NULL_H */ diff --git a/libs/smux/include/stg/NativeEnumerated.h b/libs/smux/include/stg/NativeEnumerated.h new file mode 100644 index 00000000..c59bb1ba --- /dev/null +++ b/libs/smux/include/stg/NativeEnumerated.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard ENUMERATED in that it is modelled using + * the fixed machine type (long, int, short), so it can hold only values of + * limited length. There is no type (i.e., NativeEnumerated_t, any integer type + * will do). + * This type may be used when integer range is limited by subtype constraints. + */ +#ifndef _NativeEnumerated_H_ +#define _NativeEnumerated_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeEnumerated; + +xer_type_encoder_f NativeEnumerated_encode_xer; +per_type_decoder_f NativeEnumerated_decode_uper; +per_type_encoder_f NativeEnumerated_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _NativeEnumerated_H_ */ diff --git a/libs/smux/include/stg/NativeInteger.h b/libs/smux/include/stg/NativeInteger.h new file mode 100644 index 00000000..4e63a835 --- /dev/null +++ b/libs/smux/include/stg/NativeInteger.h @@ -0,0 +1,37 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This type differs from the standard INTEGER in that it is modelled using + * the fixed machine type (long, int, short), so it can hold only values of + * limited length. There is no type (i.e., NativeInteger_t, any integer type + * will do). + * This type may be used when integer range is limited by subtype constraints. + */ +#ifndef _NativeInteger_H_ +#define _NativeInteger_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern asn_TYPE_descriptor_t asn_DEF_NativeInteger; + +asn_struct_free_f NativeInteger_free; +asn_struct_print_f NativeInteger_print; +ber_type_decoder_f NativeInteger_decode_ber; +der_type_encoder_f NativeInteger_encode_der; +xer_type_decoder_f NativeInteger_decode_xer; +xer_type_encoder_f NativeInteger_encode_xer; +per_type_decoder_f NativeInteger_decode_uper; +per_type_encoder_f NativeInteger_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _NativeInteger_H_ */ diff --git a/libs/smux/include/stg/NetworkAddress.h b/libs/smux/include/stg/NetworkAddress.h new file mode 100644 index 00000000..8c73220b --- /dev/null +++ b/libs/smux/include/stg/NetworkAddress.h @@ -0,0 +1,46 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _NetworkAddress_H_ +#define _NetworkAddress_H_ + + +#include + +/* Including external dependencies */ +#include "IpAddress.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum NetworkAddress_PR { + NetworkAddress_PR_NOTHING, /* No components present */ + NetworkAddress_PR_internet +} NetworkAddress_PR; + +/* NetworkAddress */ +typedef struct NetworkAddress { + NetworkAddress_PR present; + union NetworkAddress_u { + IpAddress_t internet; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} NetworkAddress_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_NetworkAddress; + +#ifdef __cplusplus +} +#endif + +#endif /* _NetworkAddress_H_ */ diff --git a/libs/smux/include/stg/OBJECT_IDENTIFIER.h b/libs/smux/include/stg/OBJECT_IDENTIFIER.h new file mode 100644 index 00000000..2bb5d032 --- /dev/null +++ b/libs/smux/include/stg/OBJECT_IDENTIFIER.h @@ -0,0 +1,139 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _OBJECT_IDENTIFIER_H_ +#define _OBJECT_IDENTIFIER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t; + +extern asn_TYPE_descriptor_t asn_DEF_OBJECT_IDENTIFIER; + +asn_struct_print_f OBJECT_IDENTIFIER_print; +asn_constr_check_f OBJECT_IDENTIFIER_constraint; +der_type_encoder_f OBJECT_IDENTIFIER_encode_der; +xer_type_decoder_f OBJECT_IDENTIFIER_decode_xer; +xer_type_encoder_f OBJECT_IDENTIFIER_encode_xer; + +/********************************** + * Some handy conversion routines * + **********************************/ + +/* + * This function fills an (_arcs) array with OBJECT IDENTIFIER arcs + * up to specified (_arc_slots) elements. + * + * EXAMPLE: + * void print_arcs(OBJECT_IDENTIFIER_t *oid) { + * unsigned long fixed_arcs[10]; // Try with fixed space first + * unsigned long *arcs = fixed_arcs; + * int arc_type_size = sizeof(fixed_arcs[0]); // sizeof(long) + * int arc_slots = sizeof(fixed_arcs)/sizeof(fixed_arcs[0]); // 10 + * int count; // Real number of arcs. + * int i; + * + * count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, + * arc_type_size, arc_slots); + * // If necessary, reallocate arcs array and try again. + * if(count > arc_slots) { + * arc_slots = count; + * arcs = malloc(arc_type_size * arc_slots); + * if(!arcs) return; + * count = OBJECT_IDENTIFIER_get_arcs(oid, arcs, + * arc_type_size, arc_slots); + * assert(count == arc_slots); + * } + * + * // Print the contents of the arcs array. + * for(i = 0; i < count; i++) + * printf("%d\n", arcs[i]); + * + * // Avoid memory leak. + * if(arcs != fixed_arcs) free(arcs); + * } + * + * RETURN VALUES: + * -1/EINVAL: Invalid arguments (oid is missing) + * -1/ERANGE: One or more arcs have value out of array cell type range. + * >=0: Number of arcs contained in the OBJECT IDENTIFIER + * + * WARNING: The function always returns the real number of arcs, + * even if there is no sufficient (_arc_slots) provided. + */ +int OBJECT_IDENTIFIER_get_arcs(OBJECT_IDENTIFIER_t *_oid, + void *_arcs, /* e.g., unsigned int arcs[N] */ + unsigned int _arc_type_size, /* e.g., sizeof(arcs[0]) */ + unsigned int _arc_slots /* e.g., N */); + +/* + * This functions initializes the OBJECT IDENTIFIER object with + * the given set of arcs. + * The minimum of two arcs must be present; some restrictions apply. + * RETURN VALUES: + * -1/EINVAL: Invalid arguments + * -1/ERANGE: The first two arcs do not conform to ASN.1 restrictions. + * -1/ENOMEM: Memory allocation failed + * 0: The object was initialized with new arcs. + */ +int OBJECT_IDENTIFIER_set_arcs(OBJECT_IDENTIFIER_t *_oid, + const void *_arcs, /* e.g., unsigned int arcs[N] */ + unsigned int _arc_type_size, /* e.g., sizeof(arcs[0]) */ + unsigned int _arc_slots /* e.g., N */); + +/* + * Print the specified OBJECT IDENTIFIER arc. + */ +int OBJECT_IDENTIFIER_print_arc(uint8_t *arcbuf, int arclen, + int add, /* Arbitrary offset, required to process the first two arcs */ + asn_app_consume_bytes_f *cb, void *app_key); + +/* Same as above, but returns the number of written digits, instead of 0 */ +ssize_t OBJECT_IDENTIFIER__dump_arc(uint8_t *arcbuf, int arclen, int add, + asn_app_consume_bytes_f *cb, void *app_key); + +/* + * Parse the OBJECT IDENTIFIER textual representation ("1.3.6.1.4.1.9363"). + * No arc can exceed the (0..signed_long_max) range (typically, 0..2G if L32). + * This function is not specific to OBJECT IDENTIFIER, it may be used to parse + * the RELATIVE-OID data, or any other data consisting of dot-separated + * series of numeric values. + * + * If (oid_txt_length == -1), the strlen() will be invoked to determine the + * size of the (oid_text) string. + * + * After return, the optional (opt_oid_text_end) is set to the character after + * the last parsed one. (opt_oid_text_end) is never less than (oid_text). + * + * RETURN VALUES: + * -1: Parse error. + * >= 0: Number of arcs contained in the OBJECT IDENTIFIER. + * + * WARNING: The function always returns the real number of arcs, + * even if there is no sufficient (_arc_slots) provided. + * This is useful for (_arc_slots) value estimation. + */ +int OBJECT_IDENTIFIER_parse_arcs(const char *oid_text, ssize_t oid_txt_length, + long arcs[], unsigned int arcs_slots, const char **opt_oid_text_end); + +/* + * Internal functions. + * Used by RELATIVE-OID implementation in particular. + */ +int OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, + signed int add, void *value, unsigned int value_size); +int OBJECT_IDENTIFIER_set_single_arc(uint8_t *arcbuf, + const void *arcval, unsigned int arcval_size, int _prepared_order); + +#ifdef __cplusplus +} +#endif + +#endif /* _OBJECT_IDENTIFIER_H_ */ diff --git a/libs/smux/include/stg/OCTET_STRING.h b/libs/smux/include/stg/OCTET_STRING.h new file mode 100644 index 00000000..5150161a --- /dev/null +++ b/libs/smux/include/stg/OCTET_STRING.h @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _OCTET_STRING_H_ +#define _OCTET_STRING_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct OCTET_STRING { + uint8_t *buf; /* Buffer with consecutive OCTET_STRING bits */ + int size; /* Size of the buffer */ + + asn_struct_ctx_t _asn_ctx; /* Parsing across buffer boundaries */ +} OCTET_STRING_t; + +extern asn_TYPE_descriptor_t asn_DEF_OCTET_STRING; + +asn_struct_free_f OCTET_STRING_free; +asn_struct_print_f OCTET_STRING_print; +asn_struct_print_f OCTET_STRING_print_utf8; +ber_type_decoder_f OCTET_STRING_decode_ber; +der_type_encoder_f OCTET_STRING_encode_der; +xer_type_decoder_f OCTET_STRING_decode_xer_hex; /* Hexadecimal */ +xer_type_decoder_f OCTET_STRING_decode_xer_binary; /* 01010111010 */ +xer_type_decoder_f OCTET_STRING_decode_xer_utf8; /* ASCII/UTF-8 */ +xer_type_encoder_f OCTET_STRING_encode_xer; +xer_type_encoder_f OCTET_STRING_encode_xer_utf8; +per_type_decoder_f OCTET_STRING_decode_uper; +per_type_encoder_f OCTET_STRING_encode_uper; + +/****************************** + * Handy conversion routines. * + ******************************/ + +/* + * This function clears the previous value of the OCTET STRING (if any) + * and then allocates a new memory with the specified content (str/size). + * If size = -1, the size of the original string will be determined + * using strlen(str). + * If str equals to NULL, the function will silently clear the + * current contents of the OCTET STRING. + * Returns 0 if it was possible to perform operation, -1 otherwise. + */ +int OCTET_STRING_fromBuf(OCTET_STRING_t *s, const char *str, int size); + +/* Handy conversion from the C string into the OCTET STRING. */ +#define OCTET_STRING_fromString(s, str) OCTET_STRING_fromBuf(s, str, -1) + +/* + * Allocate and fill the new OCTET STRING and return a pointer to the newly + * allocated object. NULL is permitted in str: the function will just allocate + * empty OCTET STRING. + */ +OCTET_STRING_t *OCTET_STRING_new_fromBuf(asn_TYPE_descriptor_t *td, + const char *str, int size); + +/**************************** + * Internally useful stuff. * + ****************************/ + +typedef struct asn_OCTET_STRING_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the structure */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + int subvariant; /* {0,1,2} for O-S, BIT STRING or ANY */ +} asn_OCTET_STRING_specifics_t; + +#ifdef __cplusplus +} +#endif + +#endif /* _OCTET_STRING_H_ */ diff --git a/libs/smux/include/stg/ObjectName.h b/libs/smux/include/stg/ObjectName.h new file mode 100644 index 00000000..256577b3 --- /dev/null +++ b/libs/smux/include/stg/ObjectName.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _ObjectName_H_ +#define _ObjectName_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ObjectName */ +typedef OBJECT_IDENTIFIER_t ObjectName_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ObjectName; +asn_struct_free_f ObjectName_free; +asn_struct_print_f ObjectName_print; +asn_constr_check_f ObjectName_constraint; +ber_type_decoder_f ObjectName_decode_ber; +der_type_encoder_f ObjectName_encode_der; +xer_type_decoder_f ObjectName_decode_xer; +xer_type_encoder_f ObjectName_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _ObjectName_H_ */ diff --git a/libs/smux/include/stg/ObjectSyntax.h b/libs/smux/include/stg/ObjectSyntax.h new file mode 100644 index 00000000..9030accb --- /dev/null +++ b/libs/smux/include/stg/ObjectSyntax.h @@ -0,0 +1,49 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _ObjectSyntax_H_ +#define _ObjectSyntax_H_ + + +#include + +/* Including external dependencies */ +#include "SimpleSyntax.h" +#include "ApplicationSyntax.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum ObjectSyntax_PR { + ObjectSyntax_PR_NOTHING, /* No components present */ + ObjectSyntax_PR_simple, + ObjectSyntax_PR_application_wide +} ObjectSyntax_PR; + +/* ObjectSyntax */ +typedef struct ObjectSyntax { + ObjectSyntax_PR present; + union ObjectSyntax_u { + SimpleSyntax_t simple; + ApplicationSyntax_t application_wide; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} ObjectSyntax_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_ObjectSyntax; + +#ifdef __cplusplus +} +#endif + +#endif /* _ObjectSyntax_H_ */ diff --git a/libs/smux/include/stg/Opaque.h b/libs/smux/include/stg/Opaque.h new file mode 100644 index 00000000..aa8e2d5f --- /dev/null +++ b/libs/smux/include/stg/Opaque.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _Opaque_H_ +#define _Opaque_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Opaque */ +typedef OCTET_STRING_t Opaque_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_Opaque; +asn_struct_free_f Opaque_free; +asn_struct_print_f Opaque_print; +asn_constr_check_f Opaque_constraint; +ber_type_decoder_f Opaque_decode_ber; +der_type_encoder_f Opaque_encode_der; +xer_type_decoder_f Opaque_decode_xer; +xer_type_encoder_f Opaque_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _Opaque_H_ */ diff --git a/libs/smux/include/stg/OpenPDU.h b/libs/smux/include/stg/OpenPDU.h new file mode 100644 index 00000000..5d7e1da6 --- /dev/null +++ b/libs/smux/include/stg/OpenPDU.h @@ -0,0 +1,46 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _OpenPDU_H_ +#define _OpenPDU_H_ + + +#include + +/* Including external dependencies */ +#include "SimpleOpen.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum OpenPDU_PR { + OpenPDU_PR_NOTHING, /* No components present */ + OpenPDU_PR_simple +} OpenPDU_PR; + +/* OpenPDU */ +typedef struct OpenPDU { + OpenPDU_PR present; + union OpenPDU_u { + SimpleOpen_t simple; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} OpenPDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_OpenPDU; + +#ifdef __cplusplus +} +#endif + +#endif /* _OpenPDU_H_ */ diff --git a/libs/smux/include/stg/PDU.h b/libs/smux/include/stg/PDU.h new file mode 100644 index 00000000..cbc7e714 --- /dev/null +++ b/libs/smux/include/stg/PDU.h @@ -0,0 +1,51 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _PDU_H_ +#define _PDU_H_ + + +#include + +/* Including external dependencies */ +#include +#include "VarBindList.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum PDU__error_status { + PDU__error_status_noError = 0, + PDU__error_status_tooBig = 1, + PDU__error_status_noSuchName = 2, + PDU__error_status_badValue = 3, + PDU__error_status_readOnly = 4, + PDU__error_status_genErr = 5 +} e_PDU__error_status; + +/* PDU */ +typedef struct PDU { + INTEGER_t request_id; + INTEGER_t error_status; + INTEGER_t error_index; + VarBindList_t variable_bindings; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} PDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_PDU; + +#ifdef __cplusplus +} +#endif + +#endif /* _PDU_H_ */ diff --git a/libs/smux/include/stg/PDUs.h b/libs/smux/include/stg/PDUs.h new file mode 100644 index 00000000..90bb089f --- /dev/null +++ b/libs/smux/include/stg/PDUs.h @@ -0,0 +1,58 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _PDUs_H_ +#define _PDUs_H_ + + +#include + +/* Including external dependencies */ +#include "GetRequest-PDU.h" +#include "GetNextRequest-PDU.h" +#include "GetResponse-PDU.h" +#include "SetRequest-PDU.h" +#include "Trap-PDU.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum PDUs_PR { + PDUs_PR_NOTHING, /* No components present */ + PDUs_PR_get_request, + PDUs_PR_get_next_request, + PDUs_PR_get_response, + PDUs_PR_set_request, + PDUs_PR_trap +} PDUs_PR; + +/* PDUs */ +typedef struct PDUs { + PDUs_PR present; + union PDUs_u { + GetRequest_PDU_t get_request; + GetNextRequest_PDU_t get_next_request; + GetResponse_PDU_t get_response; + SetRequest_PDU_t set_request; + Trap_PDU_t trap; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} PDUs_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_PDUs; + +#ifdef __cplusplus +} +#endif + +#endif /* _PDUs_H_ */ diff --git a/libs/smux/include/stg/PhysAddress.h b/libs/smux/include/stg/PhysAddress.h new file mode 100644 index 00000000..d6c5fa17 --- /dev/null +++ b/libs/smux/include/stg/PhysAddress.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _PhysAddress_H_ +#define _PhysAddress_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* PhysAddress */ +typedef OCTET_STRING_t PhysAddress_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_PhysAddress; +asn_struct_free_f PhysAddress_free; +asn_struct_print_f PhysAddress_print; +asn_constr_check_f PhysAddress_constraint; +ber_type_decoder_f PhysAddress_decode_ber; +der_type_encoder_f PhysAddress_encode_der; +xer_type_decoder_f PhysAddress_decode_xer; +xer_type_encoder_f PhysAddress_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _PhysAddress_H_ */ diff --git a/libs/smux/include/stg/RReqPDU.h b/libs/smux/include/stg/RReqPDU.h new file mode 100644 index 00000000..17f53094 --- /dev/null +++ b/libs/smux/include/stg/RReqPDU.h @@ -0,0 +1,48 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _RReqPDU_H_ +#define _RReqPDU_H_ + + +#include + +/* Including external dependencies */ +#include "ObjectName.h" +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum RReqPDU__operation { + RReqPDU__operation_delete = 0, + RReqPDU__operation_readOnly = 1, + RReqPDU__operation_readWrite = 2 +} e_RReqPDU__operation; + +/* RReqPDU */ +typedef struct RReqPDU { + ObjectName_t subtree; + long priority; + INTEGER_t operation; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} RReqPDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_RReqPDU; + +#ifdef __cplusplus +} +#endif + +#endif /* _RReqPDU_H_ */ diff --git a/libs/smux/include/stg/RRspPDU.h b/libs/smux/include/stg/RRspPDU.h new file mode 100644 index 00000000..0d9681ac --- /dev/null +++ b/libs/smux/include/stg/RRspPDU.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _RRspPDU_H_ +#define _RRspPDU_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum RRspPDU { + RRspPDU_failure = -1 +} e_RRspPDU; + +/* RRspPDU */ +typedef INTEGER_t RRspPDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_RRspPDU; +asn_struct_free_f RRspPDU_free; +asn_struct_print_f RRspPDU_print; +asn_constr_check_f RRspPDU_constraint; +ber_type_decoder_f RRspPDU_decode_ber; +der_type_encoder_f RRspPDU_encode_der; +xer_type_decoder_f RRspPDU_decode_xer; +xer_type_encoder_f RRspPDU_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _RRspPDU_H_ */ diff --git a/libs/smux/include/stg/SMUX-PDUs.h b/libs/smux/include/stg/SMUX-PDUs.h new file mode 100644 index 00000000..84893249 --- /dev/null +++ b/libs/smux/include/stg/SMUX-PDUs.h @@ -0,0 +1,61 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _SMUX_PDUs_H_ +#define _SMUX_PDUs_H_ + + +#include + +/* Including external dependencies */ +#include "OpenPDU.h" +#include "ClosePDU.h" +#include "RReqPDU.h" +#include "RRspPDU.h" +#include "PDUs.h" +#include "SOutPDU.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum SMUX_PDUs_PR { + SMUX_PDUs_PR_NOTHING, /* No components present */ + SMUX_PDUs_PR_open, + SMUX_PDUs_PR_close, + SMUX_PDUs_PR_registerRequest, + SMUX_PDUs_PR_registerResponse, + SMUX_PDUs_PR_pdus, + SMUX_PDUs_PR_commitOrRollback +} SMUX_PDUs_PR; + +/* SMUX-PDUs */ +typedef struct SMUX_PDUs { + SMUX_PDUs_PR present; + union SMUX_PDUs_u { + OpenPDU_t open; + ClosePDU_t close; + RReqPDU_t registerRequest; + RRspPDU_t registerResponse; + PDUs_t pdus; + SOutPDU_t commitOrRollback; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} SMUX_PDUs_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_SMUX_PDUs; + +#ifdef __cplusplus +} +#endif + +#endif /* _SMUX_PDUs_H_ */ diff --git a/libs/smux/include/stg/SOutPDU.h b/libs/smux/include/stg/SOutPDU.h new file mode 100644 index 00000000..55e76185 --- /dev/null +++ b/libs/smux/include/stg/SOutPDU.h @@ -0,0 +1,44 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _SOutPDU_H_ +#define _SOutPDU_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum SOutPDU { + SOutPDU_commit = 0, + SOutPDU_rollback = 1 +} e_SOutPDU; + +/* SOutPDU */ +typedef INTEGER_t SOutPDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_SOutPDU; +asn_struct_free_f SOutPDU_free; +asn_struct_print_f SOutPDU_print; +asn_constr_check_f SOutPDU_constraint; +ber_type_decoder_f SOutPDU_decode_ber; +der_type_encoder_f SOutPDU_encode_der; +xer_type_decoder_f SOutPDU_decode_xer; +xer_type_encoder_f SOutPDU_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _SOutPDU_H_ */ diff --git a/libs/smux/include/stg/SetRequest-PDU.h b/libs/smux/include/stg/SetRequest-PDU.h new file mode 100644 index 00000000..8854574c --- /dev/null +++ b/libs/smux/include/stg/SetRequest-PDU.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _SetRequest_PDU_H_ +#define _SetRequest_PDU_H_ + + +#include + +/* Including external dependencies */ +#include "PDU.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* SetRequest-PDU */ +typedef PDU_t SetRequest_PDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_SetRequest_PDU; +asn_struct_free_f SetRequest_PDU_free; +asn_struct_print_f SetRequest_PDU_print; +asn_constr_check_f SetRequest_PDU_constraint; +ber_type_decoder_f SetRequest_PDU_decode_ber; +der_type_encoder_f SetRequest_PDU_encode_der; +xer_type_decoder_f SetRequest_PDU_decode_xer; +xer_type_encoder_f SetRequest_PDU_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _SetRequest_PDU_H_ */ diff --git a/libs/smux/include/stg/SimpleOpen.h b/libs/smux/include/stg/SimpleOpen.h new file mode 100644 index 00000000..5950a6c1 --- /dev/null +++ b/libs/smux/include/stg/SimpleOpen.h @@ -0,0 +1,48 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "SMUX" + * found in "SMUX.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _SimpleOpen_H_ +#define _SimpleOpen_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include "DisplayString.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum SimpleOpen__version { + SimpleOpen__version_version_1 = 0 +} e_SimpleOpen__version; + +/* SimpleOpen */ +typedef struct SimpleOpen { + INTEGER_t version; + OBJECT_IDENTIFIER_t identity; + DisplayString_t description; + OCTET_STRING_t password; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} SimpleOpen_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_SimpleOpen; + +#ifdef __cplusplus +} +#endif + +#endif /* _SimpleOpen_H_ */ diff --git a/libs/smux/include/stg/SimpleSyntax.h b/libs/smux/include/stg/SimpleSyntax.h new file mode 100644 index 00000000..c04f3ab2 --- /dev/null +++ b/libs/smux/include/stg/SimpleSyntax.h @@ -0,0 +1,55 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _SimpleSyntax_H_ +#define _SimpleSyntax_H_ + + +#include + +/* Including external dependencies */ +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum SimpleSyntax_PR { + SimpleSyntax_PR_NOTHING, /* No components present */ + SimpleSyntax_PR_number, + SimpleSyntax_PR_string, + SimpleSyntax_PR_object, + SimpleSyntax_PR_empty +} SimpleSyntax_PR; + +/* SimpleSyntax */ +typedef struct SimpleSyntax { + SimpleSyntax_PR present; + union SimpleSyntax_u { + INTEGER_t number; + OCTET_STRING_t string; + OBJECT_IDENTIFIER_t object; + NULL_t empty; + } choice; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} SimpleSyntax_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_SimpleSyntax; + +#ifdef __cplusplus +} +#endif + +#endif /* _SimpleSyntax_H_ */ diff --git a/libs/smux/include/stg/TcpConnEntry.h b/libs/smux/include/stg/TcpConnEntry.h new file mode 100644 index 00000000..3160e31f --- /dev/null +++ b/libs/smux/include/stg/TcpConnEntry.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _TcpConnEntry_H_ +#define _TcpConnEntry_H_ + + +#include + +/* Including external dependencies */ +#include +#include "IpAddress.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* TcpConnEntry */ +typedef struct TcpConnEntry { + INTEGER_t tcpConnState; + IpAddress_t tcpConnLocalAddress; + long tcpConnLocalPort; + IpAddress_t tcpConnRemAddress; + long tcpConnRemPort; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} TcpConnEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_TcpConnEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _TcpConnEntry_H_ */ diff --git a/libs/smux/include/stg/TimeTicks.h b/libs/smux/include/stg/TimeTicks.h new file mode 100644 index 00000000..ea92820f --- /dev/null +++ b/libs/smux/include/stg/TimeTicks.h @@ -0,0 +1,38 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1155-SMI" + * found in "RFC1155-SMI.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _TimeTicks_H_ +#define _TimeTicks_H_ + + +#include + +/* Including external dependencies */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* TimeTicks */ +typedef INTEGER_t TimeTicks_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_TimeTicks; +asn_struct_free_f TimeTicks_free; +asn_struct_print_f TimeTicks_print; +asn_constr_check_f TimeTicks_constraint; +ber_type_decoder_f TimeTicks_decode_ber; +der_type_encoder_f TimeTicks_encode_der; +xer_type_decoder_f TimeTicks_decode_xer; +xer_type_encoder_f TimeTicks_encode_xer; + +#ifdef __cplusplus +} +#endif + +#endif /* _TimeTicks_H_ */ diff --git a/libs/smux/include/stg/Trap-PDU.h b/libs/smux/include/stg/Trap-PDU.h new file mode 100644 index 00000000..d8a89e11 --- /dev/null +++ b/libs/smux/include/stg/Trap-PDU.h @@ -0,0 +1,57 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _Trap_PDU_H_ +#define _Trap_PDU_H_ + + +#include + +/* Including external dependencies */ +#include +#include "NetworkAddress.h" +#include +#include "TimeTicks.h" +#include "VarBindList.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dependencies */ +typedef enum Trap_PDU__generic_trap { + Trap_PDU__generic_trap_coldStart = 0, + Trap_PDU__generic_trap_warmStart = 1, + Trap_PDU__generic_trap_linkDown = 2, + Trap_PDU__generic_trap_linkUp = 3, + Trap_PDU__generic_trap_authenticationFailure = 4, + Trap_PDU__generic_trap_egpNeighborLoss = 5, + Trap_PDU__generic_trap_enterpriseSpecific = 6 +} e_Trap_PDU__generic_trap; + +/* Trap-PDU */ +typedef struct Trap_PDU { + OBJECT_IDENTIFIER_t enterprise; + NetworkAddress_t agent_addr; + INTEGER_t generic_trap; + INTEGER_t specific_trap; + TimeTicks_t time_stamp; + VarBindList_t variable_bindings; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} Trap_PDU_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_Trap_PDU; + +#ifdef __cplusplus +} +#endif + +#endif /* _Trap_PDU_H_ */ diff --git a/libs/smux/include/stg/UdpEntry.h b/libs/smux/include/stg/UdpEntry.h new file mode 100644 index 00000000..e4a10264 --- /dev/null +++ b/libs/smux/include/stg/UdpEntry.h @@ -0,0 +1,39 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1213-MIB" + * found in "RFC1213-MIB.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _UdpEntry_H_ +#define _UdpEntry_H_ + + +#include + +/* Including external dependencies */ +#include "IpAddress.h" +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* UdpEntry */ +typedef struct UdpEntry { + IpAddress_t udpLocalAddress; + long udpLocalPort; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} UdpEntry_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_UdpEntry; + +#ifdef __cplusplus +} +#endif + +#endif /* _UdpEntry_H_ */ diff --git a/libs/smux/include/stg/VarBind.h b/libs/smux/include/stg/VarBind.h new file mode 100644 index 00000000..63ecad5f --- /dev/null +++ b/libs/smux/include/stg/VarBind.h @@ -0,0 +1,39 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _VarBind_H_ +#define _VarBind_H_ + + +#include + +/* Including external dependencies */ +#include "ObjectName.h" +#include "ObjectSyntax.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* VarBind */ +typedef struct VarBind { + ObjectName_t name; + ObjectSyntax_t value; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} VarBind_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_VarBind; + +#ifdef __cplusplus +} +#endif + +#endif /* _VarBind_H_ */ diff --git a/libs/smux/include/stg/VarBindList.h b/libs/smux/include/stg/VarBindList.h new file mode 100644 index 00000000..36ef1617 --- /dev/null +++ b/libs/smux/include/stg/VarBindList.h @@ -0,0 +1,43 @@ +/* + * Generated by asn1c-0.9.21 (http://lionet.info/asn1c) + * From ASN.1 module "RFC1157-SNMP" + * found in "RFC1157-SNMP.asn1" + * `asn1c -fskeletons-copy` + */ + +#ifndef _VarBindList_H_ +#define _VarBindList_H_ + + +#include + +/* Including external dependencies */ +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Forward declarations */ +struct VarBind; + +/* VarBindList */ +typedef struct VarBindList { + A_SEQUENCE_OF(struct VarBind) list; + + /* Context for parsing across buffer boundaries */ + asn_struct_ctx_t _asn_ctx; +} VarBindList_t; + +/* Implementation */ +extern asn_TYPE_descriptor_t asn_DEF_VarBindList; + +#ifdef __cplusplus +} +#endif + +/* Referred external types */ +#include "VarBind.h" + +#endif /* _VarBindList_H_ */ diff --git a/libs/smux/include/stg/asn_SEQUENCE_OF.h b/libs/smux/include/stg/asn_SEQUENCE_OF.h new file mode 100644 index 00000000..e678f034 --- /dev/null +++ b/libs/smux/include/stg/asn_SEQUENCE_OF.h @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_SEQUENCE_OF_H +#define ASN_SEQUENCE_OF_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * SEQUENCE OF is the same as SET OF with a tiny difference: + * the delete operation preserves the initial order of elements + * and thus MAY operate in non-constant time. + */ +#define A_SEQUENCE_OF(type) A_SET_OF(type) + +#define ASN_SEQUENCE_ADD(headptr, ptr) \ + asn_sequence_add((headptr), (ptr)) + +/*********************************************** + * Implementation of the SEQUENCE OF structure. + */ + +#define asn_sequence_add asn_set_add +#define asn_sequence_empty asn_set_empty + +/* + * Delete the element from the set by its number (base 0). + * This is NOT a constant-time operation. + * The order of elements is preserved. + * If _do_free is given AND the (*free) is initialized, the element + * will be freed using the custom (*free) function as well. + */ +void asn_sequence_del(void *asn_sequence_of_x, int number, int _do_free); + +/* + * Cope with different conversions requirements to/from void in C and C++. + * This is mostly useful for support library. + */ +typedef A_SEQUENCE_OF(void) asn_anonymous_sequence_; +#define _A_SEQUENCE_FROM_VOID(ptr) ((asn_anonymous_sequence_ *)(ptr)) +#define _A_CSEQUENCE_FROM_VOID(ptr) ((const asn_anonymous_sequence_ *)(ptr)) + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_SEQUENCE_OF_H */ diff --git a/libs/smux/include/stg/asn_SET_OF.h b/libs/smux/include/stg/asn_SET_OF.h new file mode 100644 index 00000000..7edf14b5 --- /dev/null +++ b/libs/smux/include/stg/asn_SET_OF.h @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_SET_OF_H +#define ASN_SET_OF_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define A_SET_OF(type) \ + struct { \ + type **array; \ + int count; /* Meaningful size */ \ + int size; /* Allocated size */ \ + void (*free)(type *); \ + } + +#define ASN_SET_ADD(headptr, ptr) \ + asn_set_add((headptr), (ptr)) + +/******************************************* + * Implementation of the SET OF structure. + */ + +/* + * Add another structure into the set by its pointer. + * RETURN VALUES: + * 0 for success and -1/errno for failure. + */ +int asn_set_add(void *asn_set_of_x, void *ptr); + +/* + * Delete the element from the set by its number (base 0). + * This is a constant-time operation. The order of elements before the + * deleted ones is guaranteed, the order of elements after the deleted + * one is NOT guaranteed. + * If _do_free is given AND the (*free) is initialized, the element + * will be freed using the custom (*free) function as well. + */ +void asn_set_del(void *asn_set_of_x, int number, int _do_free); + +/* + * Empty the contents of the set. Will free the elements, if (*free) is given. + * Will NOT free the set itself. + */ +void asn_set_empty(void *asn_set_of_x); + +/* + * Cope with different conversions requirements to/from void in C and C++. + * This is mostly useful for support library. + */ +typedef A_SET_OF(void) asn_anonymous_set_; +#define _A_SET_FROM_VOID(ptr) ((asn_anonymous_set_ *)(ptr)) +#define _A_CSET_FROM_VOID(ptr) ((const asn_anonymous_set_ *)(ptr)) + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_SET_OF_H */ diff --git a/libs/smux/include/stg/asn_application.h b/libs/smux/include/stg/asn_application.h new file mode 100644 index 00000000..f40cd86a --- /dev/null +++ b/libs/smux/include/stg/asn_application.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2004, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Application-level ASN.1 callbacks. + */ +#ifndef _ASN_APPLICATION_H_ +#define _ASN_APPLICATION_H_ + +#include "asn_system.h" /* for platform-dependent types */ +#include "asn_codecs.h" /* for ASN.1 codecs specifics */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Generic type of an application-defined callback to return various + * types of data to the application. + * EXPECTED RETURN VALUES: + * -1: Failed to consume bytes. Abort the mission. + * Non-negative return values indicate success, and ignored. + */ +typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size, + void *application_specific_key); + +/* + * A callback of this type is called whenever constraint validation fails + * on some ASN.1 type. See "constraints.h" for more details on constraint + * validation. + * This callback specifies a descriptor of the ASN.1 type which failed + * the constraint check, as well as human readable message on what + * particular constraint has failed. + */ +typedef void (asn_app_constraint_failed_f)(void *application_specific_key, + struct asn_TYPE_descriptor_s *type_descriptor_which_failed, + const void *structure_which_failed_ptr, + const char *error_message_format, ...) GCC_PRINTFLIKE(4, 5); + +#ifdef __cplusplus +} +#endif + +#include "constr_TYPE.h" /* for asn_TYPE_descriptor_t */ + +#endif /* _ASN_APPLICATION_H_ */ diff --git a/libs/smux/include/stg/asn_codecs.h b/libs/smux/include/stg/asn_codecs.h new file mode 100644 index 00000000..4a251d94 --- /dev/null +++ b/libs/smux/include/stg/asn_codecs.h @@ -0,0 +1,109 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _ASN_CODECS_H_ +#define _ASN_CODECS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * This structure defines a set of parameters that may be passed + * to every ASN.1 encoder or decoder function. + * WARNING: if max_stack_size member is set, and you are calling the + * function pointers of the asn_TYPE_descriptor_t directly, + * this structure must be ALLOCATED ON THE STACK! + * If you can't always satisfy this requirement, use ber_decode(), + * xer_decode() and uper_decode() functions instead. + */ +typedef struct asn_codec_ctx_s { + /* + * Limit the decoder routines to use no (much) more stack than a given + * number of bytes. Most of decoders are stack-based, and this + * would protect against stack overflows if the number of nested + * encodings is high. + * The OCTET STRING, BIT STRING and ANY BER decoders are heap-based, + * and are safe from this kind of overflow. + * A value from getrlimit(RLIMIT_STACK) may be used to initialize + * this variable. Be careful in multithreaded environments, as the + * stack size is rather limited. + */ + size_t max_stack_size; /* 0 disables stack bounds checking */ +} asn_codec_ctx_t; + +/* + * Type of the return value of the encoding functions (der_encode, xer_encode). + */ +typedef struct asn_enc_rval_s { + /* + * Number of bytes encoded. + * -1 indicates failure to encode the structure. + * In this case, the members below this one are meaningful. + */ + ssize_t encoded; + + /* + * Members meaningful when (encoded == -1), for post mortem analysis. + */ + + /* Type which cannot be encoded */ + struct asn_TYPE_descriptor_s *failed_type; + + /* Pointer to the structure of that type */ + void *structure_ptr; +} asn_enc_rval_t; +#define _ASN_ENCODE_FAILED do { \ + asn_enc_rval_t tmp_error; \ + tmp_error.encoded = -1; \ + tmp_error.failed_type = td; \ + tmp_error.structure_ptr = sptr; \ + ASN_DEBUG("Failed to encode element %s", td->name); \ + return tmp_error; \ +} while(0) +#define _ASN_ENCODED_OK(rval) do { \ + rval.structure_ptr = 0; \ + rval.failed_type = 0; \ + return rval; \ +} while(0) + +/* + * Type of the return value of the decoding functions (ber_decode, xer_decode) + * + * Please note that the number of consumed bytes is ALWAYS meaningful, + * even if code==RC_FAIL. This is to indicate the number of successfully + * decoded bytes, hence providing a possibility to fail with more diagnostics + * (i.e., print the offending remainder of the buffer). + */ +enum asn_dec_rval_code_e { + RC_OK, /* Decoded successfully */ + RC_WMORE, /* More data expected, call again */ + RC_FAIL /* Failure to decode data */ +}; +typedef struct asn_dec_rval_s { + enum asn_dec_rval_code_e code; /* Result code */ + size_t consumed; /* Number of bytes consumed */ +} asn_dec_rval_t; +#define _ASN_DECODE_FAILED do { \ + asn_dec_rval_t tmp_error; \ + tmp_error.code = RC_FAIL; \ + tmp_error.consumed = 0; \ + ASN_DEBUG("Failed to decode element %s", td->name); \ + return tmp_error; \ +} while(0) +#define _ASN_DECODE_STARVED do { \ + asn_dec_rval_t tmp_error; \ + tmp_error.code = RC_WMORE; \ + tmp_error.consumed = 0; \ + return tmp_error; \ +} while(0) + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN_CODECS_H_ */ diff --git a/libs/smux/include/stg/asn_codecs_prim.h b/libs/smux/include/stg/asn_codecs_prim.h new file mode 100644 index 00000000..0f683fdd --- /dev/null +++ b/libs/smux/include/stg/asn_codecs_prim.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef ASN_CODECS_PRIM_H +#define ASN_CODECS_PRIM_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ASN__PRIMITIVE_TYPE_s { + uint8_t *buf; /* Buffer with consecutive primitive encoding bytes */ + int size; /* Size of the buffer */ +} ASN__PRIMITIVE_TYPE_t; /* Do not use this type directly! */ + +asn_struct_free_f ASN__PRIMITIVE_TYPE_free; +ber_type_decoder_f ber_decode_primitive; +der_type_encoder_f der_encode_primitive; + +/* + * A callback specification for the xer_decode_primitive() function below. + */ +enum xer_pbd_rval { + XPBD_SYSTEM_FAILURE, /* System failure (memory shortage, etc) */ + XPBD_DECODER_LIMIT, /* Hit some decoder limitation or deficiency */ + XPBD_BROKEN_ENCODING, /* Encoding of a primitive body is broken */ + XPBD_NOT_BODY_IGNORE, /* Not a body format, but safe to ignore */ + XPBD_BODY_CONSUMED /* Body is recognized and consumed */ +}; +typedef enum xer_pbd_rval (xer_primitive_body_decoder_f) + (asn_TYPE_descriptor_t *td, void *struct_ptr, + const void *chunk_buf, size_t chunk_size); + +/* + * Specific function to decode simple primitive types. + * Also see xer_decode_general() in xer_decoder.h + */ +asn_dec_rval_t xer_decode_primitive(asn_codec_ctx_t *opt_codec_ctx, + asn_TYPE_descriptor_t *type_descriptor, + void **struct_ptr, size_t struct_size, + const char *opt_mname, + const void *buf_ptr, size_t size, + xer_primitive_body_decoder_f *prim_body_decoder +); + +#ifdef __cplusplus +} +#endif + +#endif /* ASN_CODECS_PRIM_H */ diff --git a/libs/smux/include/stg/asn_internal.h b/libs/smux/include/stg/asn_internal.h new file mode 100644 index 00000000..67f055a6 --- /dev/null +++ b/libs/smux/include/stg/asn_internal.h @@ -0,0 +1,111 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Declarations internally useful for the ASN.1 support code. + */ +#ifndef _ASN_INTERNAL_H_ +#define _ASN_INTERNAL_H_ + +#include "asn_application.h" /* Application-visible API */ + +#ifndef __NO_ASSERT_H__ /* Include assert.h only for internal use. */ +#include /* for assert() macro */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Environment version might be used to avoid running with the old library */ +#define ASN1C_ENVIRONMENT_VERSION 920 /* Compile-time version */ +int get_asn1c_environment_version(void); /* Run-time version */ + +#define CALLOC(nmemb, size) calloc(nmemb, size) +#define MALLOC(size) malloc(size) +#define REALLOC(oldptr, size) realloc(oldptr, size) +#define FREEMEM(ptr) free(ptr) + +/* + * A macro for debugging the ASN.1 internals. + * You may enable or override it. + */ +#ifndef ASN_DEBUG /* If debugging code is not defined elsewhere... */ +#if EMIT_ASN_DEBUG == 1 /* And it was asked to emit this code... */ +#ifdef __GNUC__ +#define ASN_DEBUG(fmt, args...) do { \ + fprintf(stderr, fmt, ##args); \ + fprintf(stderr, " (%s:%d)\n", \ + __FILE__, __LINE__); \ + } while(0) +#else /* !__GNUC__ */ +void ASN_DEBUG_f(const char *fmt, ...); +#define ASN_DEBUG ASN_DEBUG_f +#endif /* __GNUC__ */ +#else /* EMIT_ASN_DEBUG != 1 */ +static inline void ASN_DEBUG(const char *fmt, ...) { (void)fmt; } +#endif /* EMIT_ASN_DEBUG */ +#endif /* ASN_DEBUG */ + +/* + * Invoke the application-supplied callback and fail, if something is wrong. + */ +#define __ASN_E_cbc(buf, size) (cb((buf), (size), app_key) < 0) +#define _ASN_E_CALLBACK(foo) do { \ + if(foo) goto cb_failed; \ + } while(0) +#define _ASN_CALLBACK(buf, size) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf, size)) +#define _ASN_CALLBACK2(buf1, size1, buf2, size2) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) || __ASN_E_cbc(buf2, size2)) +#define _ASN_CALLBACK3(buf1, size1, buf2, size2, buf3, size3) \ + _ASN_E_CALLBACK(__ASN_E_cbc(buf1, size1) \ + || __ASN_E_cbc(buf2, size2) \ + || __ASN_E_cbc(buf3, size3)) + +#define _i_ASN_TEXT_INDENT(nl, level) do { \ + int __level = (level); \ + int __nl = ((nl) != 0); \ + int __i; \ + if(__nl) _ASN_CALLBACK("\n", 1); \ + for(__i = 0; __i < __level; __i++) \ + _ASN_CALLBACK(" ", 4); \ + er.encoded += __nl + 4 * __level; \ +} while(0) + +#define _i_INDENT(nl) do { \ + int __i; \ + if((nl) && cb("\n", 1, app_key) < 0) return -1; \ + for(__i = 0; __i < ilevel; __i++) \ + if(cb(" ", 4, app_key) < 0) return -1; \ +} while(0) + +/* + * Check stack against overflow, if limit is set. + */ +#define _ASN_DEFAULT_STACK_MAX (30000) +static inline int +_ASN_STACK_OVERFLOW_CHECK(asn_codec_ctx_t *ctx) { + if(ctx && ctx->max_stack_size) { + + /* ctx MUST be allocated on the stack */ + ptrdiff_t usedstack = ((char *)ctx - (char *)&ctx); + if(usedstack > 0) usedstack = -usedstack; /* grows up! */ + + /* double negative required to avoid int wrap-around */ + if(usedstack < -(ptrdiff_t)ctx->max_stack_size) { + ASN_DEBUG("Stack limit %ld reached", + (long)ctx->max_stack_size); + return -1; + } + } + return 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN_INTERNAL_H_ */ diff --git a/libs/smux/include/stg/asn_system.h b/libs/smux/include/stg/asn_system.h new file mode 100644 index 00000000..d7ebdaa4 --- /dev/null +++ b/libs/smux/include/stg/asn_system.h @@ -0,0 +1,104 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * Miscellaneous system-dependent types. + */ +#ifndef _ASN_SYSTEM_H_ +#define _ASN_SYSTEM_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* For snprintf(3) */ +#include /* For *alloc(3) */ +#include /* For memcpy(3) */ +#include /* For size_t */ +#include /* For va_start */ +#include /* for offsetof and ptrdiff_t */ + +#ifdef WIN32 + +#include +#include +#define snprintf _snprintf +#define vsnprintf _vsnprintf + +#ifdef _MSC_VER /* MSVS.Net */ +#ifndef __cplusplus +#define inline __inline +#endif +#define ssize_t SSIZE_T +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#define WIN32_LEAN_AND_MEAN +#include +#include +#define isnan _isnan +#define finite _finite +#define copysign _copysign +#define ilogb _logb +#endif /* _MSC_VER */ + +#else /* !WIN32 */ + +#if defined(__vxworks) +#include +#else /* !defined(__vxworks) */ + +#include /* C99 specifies this file */ +/* + * 1. Earlier FreeBSD version didn't have , + * but was present. + * 2. Sun Solaris requires for alloca(3), + * but does not have . + */ +#if (!defined(__FreeBSD__) || !defined(_SYS_INTTYPES_H_)) +#if defined(sun) +#include /* For alloca(3) */ +#include /* for finite(3) */ +#elif defined(__hpux) +#ifdef __GNUC__ +#include /* For alloca(3) */ +#else /* !__GNUC__ */ +#define inline +#endif /* __GNUC__ */ +#else +#include /* SUSv2+ and C99 specify this file, for uintXX_t */ +#endif /* defined(sun) */ +#endif + +#endif /* defined(__vxworks) */ + +#endif /* WIN32 */ + +#if __GNUC__ >= 3 +#ifndef GCC_PRINTFLIKE +#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) +#endif +#else +#ifndef GCC_PRINTFLIKE +#define GCC_PRINTFLIKE(fmt,var) /* nothing */ +#endif +#endif + +#ifndef offsetof /* If not defined by */ +#define offsetof(s, m) ((ptrdiff_t)&(((s *)0)->m) - (ptrdiff_t)((s *)0)) +#endif /* offsetof */ + +#ifndef MIN /* Suitable for comparing primitive types (integers) */ +#if defined(__GNUC__) +#define MIN(a,b) ({ __typeof a _a = a; __typeof b _b = b; \ + ((_a)<(_b)?(_a):(_b)); }) +#else /* !__GNUC__ */ +#define MIN(a,b) ((a)<(b)?(a):(b)) /* Unsafe variant */ +#endif /* __GNUC__ */ +#endif /* MIN */ + +#endif /* _ASN_SYSTEM_H_ */ diff --git a/libs/smux/include/stg/ber_decoder.h b/libs/smux/include/stg/ber_decoder.h new file mode 100644 index 00000000..768133b6 --- /dev/null +++ b/libs/smux/include/stg/ber_decoder.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_DECODER_H_ +#define _BER_DECODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ +struct asn_codec_ctx_s; /* Forward declaration */ + +/* + * The BER decoder of any type. + * This function may be invoked directly from the application. + */ +asn_dec_rval_t ber_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of that buffer */ + ); + +/* + * Type of generic function which decodes the byte stream into the structure. + */ +typedef asn_dec_rval_t (ber_type_decoder_f)( + struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, const void *buf_ptr, size_t size, + int tag_mode); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Check that all tags correspond to the type definition (as given in head). + * On return, last_length would contain either a non-negative length of the + * value part of the last TLV, or the negative number of expected + * "end of content" sequences. The number may only be negative if the + * head->last_tag_form is non-zero. + */ +asn_dec_rval_t ber_check_tags( + struct asn_codec_ctx_s *opt_codec_ctx, /* codec options */ + struct asn_TYPE_descriptor_s *type_descriptor, + asn_struct_ctx_t *opt_ctx, /* saved decoding context */ + const void *ptr, size_t size, + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + int last_tag_form, /* {-1,0:1}: any, primitive, constr */ + ber_tlv_len_t *last_length, + int *opt_tlv_form /* optional tag form */ + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_DECODER_H_ */ diff --git a/libs/smux/include/stg/ber_tlv_length.h b/libs/smux/include/stg/ber_tlv_length.h new file mode 100644 index 00000000..34968022 --- /dev/null +++ b/libs/smux/include/stg/ber_tlv_length.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_TLV_LENGTH_H_ +#define _BER_TLV_LENGTH_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef ssize_t ber_tlv_len_t; + +/* + * This function tries to fetch the length of the BER TLV value and place it + * in *len_r. + * RETURN VALUES: + * 0: More data expected than bufptr contains. + * -1: Fatal error deciphering length. + * >0: Number of bytes used from bufptr. + * On return with >0, len_r is constrained as -1..MAX, where -1 mean + * that the value is of indefinite length. + */ +ssize_t ber_fetch_length(int _is_constructed, const void *bufptr, size_t size, + ber_tlv_len_t *len_r); + +/* + * This function expects bufptr to be positioned over L in TLV. + * It returns number of bytes occupied by L and V together, suitable + * for skipping. The function properly handles indefinite length. + * RETURN VALUES: + * Standard {-1,0,>0} convention. + */ +ssize_t ber_skip_length( + struct asn_codec_ctx_s *opt_codec_ctx, /* optional context */ + int _is_constructed, const void *bufptr, size_t size); + +/* + * This function serializes the length (L from TLV) in DER format. + * It always returns number of bytes necessary to represent the length, + * it is a caller's responsibility to check the return value + * against the supplied buffer's size. + */ +size_t der_tlv_length_serialize(ber_tlv_len_t len, void *bufptr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_TLV_LENGTH_H_ */ diff --git a/libs/smux/include/stg/ber_tlv_tag.h b/libs/smux/include/stg/ber_tlv_tag.h new file mode 100644 index 00000000..60e86686 --- /dev/null +++ b/libs/smux/include/stg/ber_tlv_tag.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _BER_TLV_TAG_H_ +#define _BER_TLV_TAG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum asn_tag_class { + ASN_TAG_CLASS_UNIVERSAL = 0, /* 0b00 */ + ASN_TAG_CLASS_APPLICATION = 1, /* 0b01 */ + ASN_TAG_CLASS_CONTEXT = 2, /* 0b10 */ + ASN_TAG_CLASS_PRIVATE = 3 /* 0b11 */ +}; +typedef unsigned ber_tlv_tag_t; /* BER TAG from Tag-Length-Value */ + +/* + * Tag class is encoded together with tag value for optimization purposes. + */ +#define BER_TAG_CLASS(tag) ((tag) & 0x3) +#define BER_TAG_VALUE(tag) ((tag) >> 2) +#define BER_TLV_CONSTRUCTED(tagptr) (((*(const uint8_t *)tagptr)&0x20)?1:0) + +#define BER_TAGS_EQUAL(tag1, tag2) ((tag1) == (tag2)) + +/* + * Several functions for printing the TAG in the canonical form + * (i.e. "[PRIVATE 0]"). + * Return values correspond to their libc counterparts (if any). + */ +ssize_t ber_tlv_tag_snprint(ber_tlv_tag_t tag, char *buf, size_t buflen); +ssize_t ber_tlv_tag_fwrite(ber_tlv_tag_t tag, FILE *); +char *ber_tlv_tag_string(ber_tlv_tag_t tag); + + +/* + * This function tries to fetch the tag from the input stream. + * RETURN VALUES: + * 0: More data expected than bufptr contains. + * -1: Fatal error deciphering tag. + * >0: Number of bytes used from bufptr. tag_r will contain the tag. + */ +ssize_t ber_fetch_tag(const void *bufptr, size_t size, ber_tlv_tag_t *tag_r); + +/* + * This function serializes the tag (T from TLV) in BER format. + * It always returns number of bytes necessary to represent the tag, + * it is a caller's responsibility to check the return value + * against the supplied buffer's size. + */ +size_t ber_tlv_tag_serialize(ber_tlv_tag_t tag, void *bufptr, size_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _BER_TLV_TAG_H_ */ diff --git a/libs/smux/include/stg/constr_CHOICE.h b/libs/smux/include/stg/constr_CHOICE.h new file mode 100644 index 00000000..83404e6d --- /dev/null +++ b/libs/smux/include/stg/constr_CHOICE.h @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_CHOICE_H_ +#define _CONSTR_CHOICE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_CHOICE_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_codec_ctx_t member */ + int pres_offset; /* Identifier of the present member */ + int pres_size; /* Size of the identifier (enum) */ + + /* + * Tags to members mapping table. + */ + asn_TYPE_tag2member_t *tag2el; + int tag2el_count; + + /* Canonical ordering of CHOICE elements, for PER */ + int *canonical_order; + + /* + * Extensions-related stuff. + */ + int ext_start; /* First member of extensions, or -1 */ +} asn_CHOICE_specifics_t; + +/* + * A set specialized functions dealing with the CHOICE type. + */ +asn_struct_free_f CHOICE_free; +asn_struct_print_f CHOICE_print; +asn_constr_check_f CHOICE_constraint; +ber_type_decoder_f CHOICE_decode_ber; +der_type_encoder_f CHOICE_encode_der; +xer_type_decoder_f CHOICE_decode_xer; +xer_type_encoder_f CHOICE_encode_xer; +per_type_decoder_f CHOICE_decode_uper; +per_type_encoder_f CHOICE_encode_uper; +asn_outmost_tag_f CHOICE_outmost_tag; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_CHOICE_H_ */ diff --git a/libs/smux/include/stg/constr_SEQUENCE.h b/libs/smux/include/stg/constr_SEQUENCE.h new file mode 100644 index 00000000..5f589d5c --- /dev/null +++ b/libs/smux/include/stg/constr_SEQUENCE.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SEQUENCE_H_ +#define _CONSTR_SEQUENCE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_SEQUENCE_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + /* + * Tags to members mapping table (sorted). + */ + asn_TYPE_tag2member_t *tag2el; + int tag2el_count; + + /* + * Optional members of the extensions root (roms) or additions (aoms). + * Meaningful for PER. + */ + int *oms; /* Optional MemberS */ + int roms_count; /* Root optional members count */ + int aoms_count; /* Additions optional members count */ + + /* + * Description of an extensions group. + */ + int ext_after; /* Extensions start after this member */ + int ext_before; /* Extensions stop before this member */ +} asn_SEQUENCE_specifics_t; + + +/* + * A set specialized functions dealing with the SEQUENCE type. + */ +asn_struct_free_f SEQUENCE_free; +asn_struct_print_f SEQUENCE_print; +asn_constr_check_f SEQUENCE_constraint; +ber_type_decoder_f SEQUENCE_decode_ber; +der_type_encoder_f SEQUENCE_encode_der; +xer_type_decoder_f SEQUENCE_decode_xer; +xer_type_encoder_f SEQUENCE_encode_xer; +per_type_decoder_f SEQUENCE_decode_uper; +per_type_encoder_f SEQUENCE_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SEQUENCE_H_ */ diff --git a/libs/smux/include/stg/constr_SEQUENCE_OF.h b/libs/smux/include/stg/constr_SEQUENCE_OF.h new file mode 100644 index 00000000..e2272f32 --- /dev/null +++ b/libs/smux/include/stg/constr_SEQUENCE_OF.h @@ -0,0 +1,33 @@ +/*- + * Copyright (c) 2003, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SEQUENCE_OF_H_ +#define _CONSTR_SEQUENCE_OF_H_ + +#include +#include /* Implemented using SET OF */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * A set specialized functions dealing with the SEQUENCE OF type. + * Generally implemented using SET OF. + */ +#define SEQUENCE_OF_free SET_OF_free +#define SEQUENCE_OF_print SET_OF_print +#define SEQUENCE_OF_constraint SET_OF_constraint +#define SEQUENCE_OF_decode_ber SET_OF_decode_ber +#define SEQUENCE_OF_decode_xer SET_OF_decode_xer +#define SEQUENCE_OF_decode_uper SET_OF_decode_uper +der_type_encoder_f SEQUENCE_OF_encode_der; +xer_type_encoder_f SEQUENCE_OF_encode_xer; +per_type_encoder_f SEQUENCE_OF_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SET_OF_H_ */ diff --git a/libs/smux/include/stg/constr_SET_OF.h b/libs/smux/include/stg/constr_SET_OF.h new file mode 100644 index 00000000..bcd09662 --- /dev/null +++ b/libs/smux/include/stg/constr_SET_OF.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2003 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _CONSTR_SET_OF_H_ +#define _CONSTR_SET_OF_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct asn_SET_OF_specifics_s { + /* + * Target structure description. + */ + int struct_size; /* Size of the target structure. */ + int ctx_offset; /* Offset of the asn_struct_ctx_t member */ + + /* XER-specific stuff */ + int as_XMLValueList; /* The member type must be encoded like this */ +} asn_SET_OF_specifics_t; + +/* + * A set specialized functions dealing with the SET OF type. + */ +asn_struct_free_f SET_OF_free; +asn_struct_print_f SET_OF_print; +asn_constr_check_f SET_OF_constraint; +ber_type_decoder_f SET_OF_decode_ber; +der_type_encoder_f SET_OF_encode_der; +xer_type_decoder_f SET_OF_decode_xer; +xer_type_encoder_f SET_OF_encode_xer; +per_type_decoder_f SET_OF_decode_uper; +per_type_encoder_f SET_OF_encode_uper; + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_SET_OF_H_ */ diff --git a/libs/smux/include/stg/constr_TYPE.h b/libs/smux/include/stg/constr_TYPE.h new file mode 100644 index 00000000..95507c80 --- /dev/null +++ b/libs/smux/include/stg/constr_TYPE.h @@ -0,0 +1,180 @@ +/*- + * Copyright (c) 2003, 2004, 2005, 2006 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +/* + * This file contains the declaration structure called "ASN.1 Type Definition", + * which holds all information necessary for encoding and decoding routines. + * This structure even contains pointer to these encoding and decoding routines + * for each defined ASN.1 type. + */ +#ifndef _CONSTR_TYPE_H_ +#define _CONSTR_TYPE_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ +struct asn_TYPE_member_s; /* Forward declaration */ + +/* + * This type provides the context information for various ASN.1 routines, + * primarily ones doing decoding. A member _asn_ctx of this type must be + * included into certain target language's structures, such as compound types. + */ +typedef struct asn_struct_ctx_s { + short phase; /* Decoding phase */ + short step; /* Elementary step of a phase */ + int context; /* Other context information */ + void *ptr; /* Decoder-specific stuff (stack elements) */ + ber_tlv_len_t left; /* Number of bytes left, -1 for indefinite */ +} asn_struct_ctx_t; + +#include /* Basic Encoding Rules decoder */ +#include /* Distinguished Encoding Rules encoder */ +#include /* Decoder of XER (XML, text) */ +#include /* Encoder into XER (XML, text) */ +#include /* Packet Encoding Rules decoder */ +#include /* Packet Encoding Rules encoder */ +#include /* Subtype constraints support */ + +/* + * Free the structure according to its specification. + * If (free_contents_only) is set, the wrapper structure itself (struct_ptr) + * will not be freed. (It may be useful in case the structure is allocated + * statically or arranged on the stack, yet its elements are allocated + * dynamically.) + */ +typedef void (asn_struct_free_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, int free_contents_only); +#define ASN_STRUCT_FREE(asn_DEF, ptr) (asn_DEF).free_struct(&(asn_DEF),ptr,0) +#define ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF, ptr) \ + (asn_DEF).free_struct(&(asn_DEF),ptr,1) + +/* + * Print the structure according to its specification. + */ +typedef int (asn_struct_print_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, + int level, /* Indentation level */ + asn_app_consume_bytes_f *callback, void *app_key); + +/* + * Return the outmost tag of the type. + * If the type is untagged CHOICE, the dynamic operation is performed. + * NOTE: This function pointer type is only useful internally. + * Do not use it in your application. + */ +typedef ber_tlv_tag_t (asn_outmost_tag_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, int tag_mode, ber_tlv_tag_t tag); +/* The instance of the above function type; used internally. */ +asn_outmost_tag_f asn_TYPE_outmost_tag; + + +/* + * The definitive description of the destination language's structure. + */ +typedef struct asn_TYPE_descriptor_s { + char *name; /* A name of the ASN.1 type. "" in some cases. */ + char *xml_tag; /* Name used in XML tag */ + + /* + * Generalized functions for dealing with the specific type. + * May be directly invoked by applications. + */ + asn_struct_free_f *free_struct; /* Free the structure */ + asn_struct_print_f *print_struct; /* Human readable output */ + asn_constr_check_f *check_constraints; /* Constraints validator */ + ber_type_decoder_f *ber_decoder; /* Generic BER decoder */ + der_type_encoder_f *der_encoder; /* Canonical DER encoder */ + xer_type_decoder_f *xer_decoder; /* Generic XER decoder */ + xer_type_encoder_f *xer_encoder; /* [Canonical] XER encoder */ + per_type_decoder_f *uper_decoder; /* Unaligned PER decoder */ + per_type_encoder_f *uper_encoder; /* Unaligned PER encoder */ + + /*********************************************************************** + * Internally useful members. Not to be used by applications directly. * + **********************************************************************/ + + /* + * Tags that are expected to occur. + */ + asn_outmost_tag_f *outmost_tag; /* */ + ber_tlv_tag_t *tags; /* Effective tags sequence for this type */ + int tags_count; /* Number of tags which are expected */ + ber_tlv_tag_t *all_tags;/* Every tag for BER/containment */ + int all_tags_count; /* Number of tags */ + + asn_per_constraints_t *per_constraints; /* PER compiled constraints */ + + /* + * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE). + */ + struct asn_TYPE_member_s *elements; + int elements_count; + + /* + * Additional information describing the type, used by appropriate + * functions above. + */ + void *specifics; +} asn_TYPE_descriptor_t; + +/* + * This type describes an element of the constructed type, + * i.e. SEQUENCE, SET, CHOICE, etc. + */ + enum asn_TYPE_flags_e { + ATF_NOFLAGS, + ATF_POINTER = 0x01, /* Represented by the pointer */ + ATF_OPEN_TYPE = 0x02 /* ANY type, without meaningful tag */ + }; +typedef struct asn_TYPE_member_s { + enum asn_TYPE_flags_e flags; /* Element's presentation flags */ + int optional; /* Following optional members, including current */ + int memb_offset; /* Offset of the element */ + ber_tlv_tag_t tag; /* Outmost (most immediate) tag */ + int tag_mode; /* IMPLICIT/no/EXPLICIT tag at current level */ + asn_TYPE_descriptor_t *type; /* Member type descriptor */ + asn_constr_check_f *memb_constraints; /* Constraints validator */ + asn_per_constraints_t *per_constraints; /* PER compiled constraints */ + int (*default_value)(int setval, void **sptr); /* DEFAULT */ + char *name; /* ASN.1 identifier of the element */ +} asn_TYPE_member_t; + +/* + * BER tag to element number mapping. + */ +typedef struct asn_TYPE_tag2member_s { + ber_tlv_tag_t el_tag; /* Outmost tag of the member */ + int el_no; /* Index of the associated member, base 0 */ + int toff_first; /* First occurence of the el_tag, relative */ + int toff_last; /* Last occurence of the el_tag, relatvie */ +} asn_TYPE_tag2member_t; + +/* + * This function is a wrapper around (td)->print_struct, which prints out + * the contents of the target language's structure (struct_ptr) into the + * file pointer (stream) in human readable form. + * RETURN VALUES: + * 0: The structure is printed. + * -1: Problem dumping the structure. + * (See also xer_fprint() in xer_encoder.h) + */ +int asn_fprint(FILE *stream, /* Destination stream descriptor */ + asn_TYPE_descriptor_t *td, /* ASN.1 type descriptor */ + const void *struct_ptr); /* Structure to be printed */ + +#ifdef __cplusplus +} +#endif + +#endif /* _CONSTR_TYPE_H_ */ diff --git a/libs/smux/include/stg/constraints.h b/libs/smux/include/stg/constraints.h new file mode 100644 index 00000000..5032345e --- /dev/null +++ b/libs/smux/include/stg/constraints.h @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 2004, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _ASN1_CONSTRAINTS_VALIDATOR_H_ +#define _ASN1_CONSTRAINTS_VALIDATOR_H_ + +#include /* Platform-dependent types */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Validate the structure according to the ASN.1 constraints. + * If errbuf and errlen are given, they shall be pointing to the appropriate + * buffer space and its length before calling this function. Alternatively, + * they could be passed as NULL's. If constraints validation fails, + * errlen will contain the actual number of bytes taken from the errbuf + * to encode an error message (properly 0-terminated). + * + * RETURN VALUES: + * This function returns 0 in case all ASN.1 constraints are met + * and -1 if one or more constraints were failed. + */ +int +asn_check_constraints(struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, /* Target language's structure */ + char *errbuf, /* Returned error description */ + size_t *errlen /* Length of the error description */ + ); + + +/* + * Generic type for constraint checking callback, + * associated with every type descriptor. + */ +typedef int (asn_constr_check_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + const void *struct_ptr, + asn_app_constraint_failed_f *optional_callback, /* Log the error */ + void *optional_app_key /* Opaque key passed to a callback */ + ); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +asn_constr_check_f asn_generic_no_constraint; /* No constraint whatsoever */ +asn_constr_check_f asn_generic_unknown_constraint; /* Not fully supported */ + +/* + * Invoke the callback with a complete error message. + */ +#define _ASN_CTFAIL if(ctfailcb) ctfailcb + +#ifdef __cplusplus +} +#endif + +#endif /* _ASN1_CONSTRAINTS_VALIDATOR_H_ */ diff --git a/libs/smux/include/stg/der_encoder.h b/libs/smux/include/stg/der_encoder.h new file mode 100644 index 00000000..4e2fb06c --- /dev/null +++ b/libs/smux/include/stg/der_encoder.h @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _DER_ENCODER_H_ +#define _DER_ENCODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * The DER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t der_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key /* Arbitrary callback argument */ + ); + +/* A variant of der_encode() which encodes data into the pre-allocated buffer */ +asn_enc_rval_t der_encode_to_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + void *buffer, /* Pre-allocated buffer */ + size_t buffer_size /* Initial buffer size (maximum) */ + ); + +/* + * Type of the generic DER encoder. + */ +typedef asn_enc_rval_t (der_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + ber_tlv_tag_t tag, + asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */ + void *app_key /* Arbitrary callback argument */ + ); + + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Write out leading TL[v] sequence according to the type definition. + */ +ssize_t der_write_tags( + struct asn_TYPE_descriptor_s *type_descriptor, + size_t struct_length, + int tag_mode, /* {-1,0,1}: IMPLICIT, no, EXPLICIT */ + int last_tag_form, /* {0,!0}: prim, constructed */ + ber_tlv_tag_t tag, + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _DER_ENCODER_H_ */ diff --git a/libs/smux/include/stg/per_decoder.h b/libs/smux/include/stg/per_decoder.h new file mode 100644 index 00000000..26aaf594 --- /dev/null +++ b/libs/smux/include/stg/per_decoder.h @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_DECODER_H_ +#define _PER_DECODER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Unaligned PER decoder of any ASN.1 type. May be invoked by the application. + */ +asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, /* Type to decode */ + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size, /* Size of data buffer */ + int skip_bits, /* Number of unused leading bits, 0..7 */ + int unused_bits /* Number of unused tailing bits, 0..7 */ + ); + + +/* + * Type of the type-specific PER decoder function. + */ +typedef asn_dec_rval_t (per_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void **struct_ptr, + asn_per_data_t *per_data + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_DECODER_H_ */ diff --git a/libs/smux/include/stg/per_encoder.h b/libs/smux/include/stg/per_encoder.h new file mode 100644 index 00000000..9ac130b7 --- /dev/null +++ b/libs/smux/include/stg/per_encoder.h @@ -0,0 +1,49 @@ +/*- + * Copyright (c) 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_ENCODER_H_ +#define _PER_ENCODER_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * Unaligned PER encoder of any ASN.1 type. May be invoked by the application. + */ +asn_enc_rval_t uper_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + asn_app_consume_bytes_f *consume_bytes_cb, /* Data collector */ + void *app_key /* Arbitrary callback argument */ +); + +/* A variant of uper_encode() which encodes data into the existing buffer */ +asn_enc_rval_t uper_encode_to_buffer( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + void *buffer, /* Pre-allocated buffer */ + size_t buffer_size /* Initial buffer size (max) */ +); + + +/* + * Type of the generic PER encoder function. + */ +typedef asn_enc_rval_t (per_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + asn_per_constraints_t *constraints, + void *struct_ptr, + asn_per_outp_t *per_output +); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_ENCODER_H_ */ diff --git a/libs/smux/include/stg/per_support.h b/libs/smux/include/stg/per_support.h new file mode 100644 index 00000000..420bb83c --- /dev/null +++ b/libs/smux/include/stg/per_support.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _PER_SUPPORT_H_ +#define _PER_SUPPORT_H_ + +#include /* Platform-specific types */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Pre-computed PER constraints. + */ +typedef struct asn_per_constraint_s { + enum asn_per_constraint_flags { + APC_UNCONSTRAINED = 0x0, /* No PER visible constraints */ + APC_SEMI_CONSTRAINED = 0x1, /* Constrained at "lb" */ + APC_CONSTRAINED = 0x2, /* Fully constrained */ + APC_EXTENSIBLE = 0x4 /* May have extension */ + } flags; + int range_bits; /* Full number of bits in the range */ + int effective_bits; /* Effective bits */ + long lower_bound; /* "lb" value */ + long upper_bound; /* "ub" value */ +} asn_per_constraint_t; +typedef struct asn_per_constraints_s { + asn_per_constraint_t value; + asn_per_constraint_t size; +} asn_per_constraints_t; + +/* + * This structure describes a position inside an incoming PER bit stream. + */ +typedef struct asn_per_data_s { + const uint8_t *buffer; /* Pointer to the octet stream */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits in the stream */ +} asn_per_data_t; + +/* + * Extract a small number of bits (<= 31) from the specified PER data pointer. + * This function returns -1 if the specified number of bits could not be + * extracted due to EOD or other conditions. + */ +int32_t per_get_few_bits(asn_per_data_t *per_data, int get_nbits); + +/* + * Extract a large number of bits from the specified PER data pointer. + * This function returns -1 if the specified number of bits could not be + * extracted due to EOD or other conditions. + */ +int per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int right_align, + int get_nbits); + +/* + * Get the length "n" from the Unaligned PER stream. + */ +ssize_t uper_get_length(asn_per_data_t *pd, + int effective_bound_bits, + int *repeat); + +/* + * Get the normally small non-negative whole number. + */ +ssize_t uper_get_nsnnwn(asn_per_data_t *pd); + +/* + * This structure supports forming PER output. + */ +typedef struct asn_per_outp_s { + uint8_t *buffer; /* Pointer into the (tmpspace) */ + size_t nboff; /* Bit offset to the meaningful bit */ + size_t nbits; /* Number of bits left in (tmpspace) */ + uint8_t tmpspace[32]; /* Preliminary storage to hold data */ + int (*outper)(const void *data, size_t size, void *op_key); + void *op_key; /* Key for (outper) data callback */ + size_t flushed_bytes; /* Bytes already flushed through (outper) */ +} asn_per_outp_t; + +/* Output a small number of bits (<= 31) */ +int per_put_few_bits(asn_per_outp_t *per_data, uint32_t bits, int obits); + +/* Output a large number of bits */ +int per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int put_nbits); + +/* + * Put the length "n" to the Unaligned PER stream. + * This function returns the number of units which may be flushed + * in the next units saving iteration. + */ +ssize_t uper_put_length(asn_per_outp_t *po, size_t whole_length); + +/* + * Put the normally small non-negative whole number. + */ +int uper_put_nsnnwn(asn_per_outp_t *po, int n); + +#ifdef __cplusplus +} +#endif + +#endif /* _PER_SUPPORT_H_ */ diff --git a/libs/smux/include/stg/xer_decoder.h b/libs/smux/include/stg/xer_decoder.h new file mode 100644 index 00000000..cf0d846f --- /dev/null +++ b/libs/smux/include/stg/xer_decoder.h @@ -0,0 +1,106 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_DECODER_H_ +#define _XER_DECODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* + * The XER decoder of any ASN.1 type. May be invoked by the application. + */ +asn_dec_rval_t xer_decode(struct asn_codec_ctx_s *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, /* Pointer to a target structure's pointer */ + const void *buffer, /* Data to be decoded */ + size_t size /* Size of data buffer */ + ); + +/* + * Type of the type-specific XER decoder function. + */ +typedef asn_dec_rval_t (xer_type_decoder_f)(asn_codec_ctx_t *opt_codec_ctx, + struct asn_TYPE_descriptor_s *type_descriptor, + void **struct_ptr, + const char *opt_mname, /* Member name */ + const void *buf_ptr, size_t size + ); + +/******************************* + * INTERNALLY USEFUL FUNCTIONS * + *******************************/ + +/* + * Generalized function for decoding the primitive values. + * Used by more specialized functions, such as OCTET_STRING_decode_xer_utf8 + * and others. This function should not be used by applications, as its API + * is subject to changes. + */ +asn_dec_rval_t xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, + asn_struct_ctx_t *ctx, /* Type decoder context */ + void *struct_key, /* Treated as opaque pointer */ + const char *xml_tag, /* Expected XML tag name */ + const void *buf_ptr, size_t size, + int (*opt_unexpected_tag_decoder) + (void *struct_key, const void *chunk_buf, size_t chunk_size), + ssize_t (*body_receiver) + (void *struct_key, const void *chunk_buf, size_t chunk_size, + int have_more) + ); + + +/* + * Fetch the next XER (XML) token from the stream. + * The function returns the number of bytes occupied by the chunk type, + * returned in the _ch_type. The _ch_type is only set (and valid) when + * the return value is greater than 0. + */ + typedef enum pxer_chunk_type { + PXER_TAG, /* Complete XER tag */ + PXER_TEXT, /* Plain text between XER tags */ + PXER_COMMENT /* A comment, may be part of */ + } pxer_chunk_type_e; +ssize_t xer_next_token(int *stateContext, + const void *buffer, size_t size, pxer_chunk_type_e *_ch_type); + +/* + * This function checks the buffer against the tag name is expected to occur. + */ + typedef enum xer_check_tag { + XCT_BROKEN = 0, /* The tag is broken */ + XCT_OPENING = 1, /* This is the tag */ + XCT_CLOSING = 2, /* This is the tag */ + XCT_BOTH = 3, /* This is the tag */ + XCT__UNK__MASK = 4, /* Mask of everything unexpected */ + XCT_UNKNOWN_OP = 5, /* Unexpected tag */ + XCT_UNKNOWN_CL = 6, /* Unexpected tag */ + XCT_UNKNOWN_BO = 7 /* Unexpected tag */ + } xer_check_tag_e; +xer_check_tag_e xer_check_tag(const void *buf_ptr, int size, + const char *need_tag); + +/* + * Check whether this buffer consists of entirely XER whitespace characters. + * RETURN VALUES: + * 1: Whitespace or empty string + * 0: Non-whitespace + */ +int xer_is_whitespace(const void *chunk_buf, size_t chunk_size); + +/* + * Skip the series of anticipated extensions. + */ +int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_DECODER_H_ */ diff --git a/libs/smux/include/stg/xer_encoder.h b/libs/smux/include/stg/xer_encoder.h new file mode 100644 index 00000000..055e73c0 --- /dev/null +++ b/libs/smux/include/stg/xer_encoder.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_ENCODER_H_ +#define _XER_ENCODER_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct asn_TYPE_descriptor_s; /* Forward declaration */ + +/* Flags used by the xer_encode() and (*xer_type_encoder_f), defined below */ +enum xer_encoder_flags_e { + /* Mode of encoding */ + XER_F_BASIC = 0x01, /* BASIC-XER (pretty-printing) */ + XER_F_CANONICAL = 0x02 /* Canonical XER (strict rules) */ +}; + +/* + * The XER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t xer_encode(struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *consume_bytes_cb, + void *app_key /* Arbitrary callback argument */ + ); + +/* + * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC) + * output into the chosen file pointer. + * RETURN VALUES: + * 0: The structure is printed. + * -1: Problem printing the structure. + * WARNING: No sensible errno value is returned. + */ +int xer_fprint(FILE *stream, struct asn_TYPE_descriptor_s *td, void *sptr); + +/* + * Type of the generic XER encoder. + */ +typedef asn_enc_rval_t (xer_type_encoder_f)( + struct asn_TYPE_descriptor_s *type_descriptor, + void *struct_ptr, /* Structure to be encoded */ + int ilevel, /* Level of indentation */ + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *consume_bytes_cb, /* Callback */ + void *app_key /* Arbitrary callback argument */ + ); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_ENCODER_H_ */ diff --git a/libs/smux/include/stg/xer_support.h b/libs/smux/include/stg/xer_support.h new file mode 100644 index 00000000..8b01944a --- /dev/null +++ b/libs/smux/include/stg/xer_support.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com. + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#ifndef _XER_SUPPORT_H_ +#define _XER_SUPPORT_H_ + +#include /* Platform-specific types */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Types of data transferred to the application. + */ +typedef enum { + PXML_TEXT, /* Plain text between XML tags. */ + PXML_TAG, /* A tag, starting with '<'. */ + PXML_COMMENT, /* An XML comment, including "". */ + /* + * The following chunk types are reported if the chunk + * terminates the specified XML element. + */ + PXML_TAG_END, /* Tag ended */ + PXML_COMMENT_END /* Comment ended */ +} pxml_chunk_type_e; + +/* + * Callback function that is called by the parser when parsed data is + * available. The _opaque is the pointer to a field containing opaque user + * data specified in pxml_create() call. The chunk type is _type and the text + * data is the piece of buffer identified by _bufid (as supplied to + * pxml_feed() call) starting at offset _offset and of _size bytes size. + * The chunk is NOT '\0'-terminated. + */ +typedef int (pxml_callback_f)(pxml_chunk_type_e _type, + const void *_chunk_data, size_t _chunk_size, void *_key); + +/* + * Parse the given buffer as it were a chunk of XML data. + * Invoke the specified callback each time the meaninful data is found. + * This function returns number of bytes consumed from the bufer. + * It will always be lesser than or equal to the specified _size. + * The next invocation of this function must account the difference. + */ +ssize_t pxml_parse(int *_stateContext, const void *_buf, size_t _size, + pxml_callback_f *cb, void *_key); + +#ifdef __cplusplus +} +#endif + +#endif /* _XER_SUPPORT_H_ */ diff --git a/libs/smux/per_decoder.c b/libs/smux/per_decoder.c new file mode 100644 index 00000000..16dee369 --- /dev/null +++ b/libs/smux/per_decoder.c @@ -0,0 +1,55 @@ +#include +#include +#include + +asn_dec_rval_t +uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) { + asn_codec_ctx_t s_codec_ctx; + asn_dec_rval_t rval; + asn_per_data_t pd; + + if(skip_bits < 0 || skip_bits > 7 + || unused_bits < 0 || unused_bits > 7 + || (unused_bits > 0 && !size)) + _ASN_DECODE_FAILED; + + /* + * Stack checker requires that the codec context + * must be allocated on the stack. + */ + if(opt_codec_ctx) { + if(opt_codec_ctx->max_stack_size) { + s_codec_ctx = *opt_codec_ctx; + opt_codec_ctx = &s_codec_ctx; + } + } else { + /* If context is not given, be security-conscious anyway */ + memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); + s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX; + opt_codec_ctx = &s_codec_ctx; + } + + /* Fill in the position indicator */ + pd.buffer = (const uint8_t *)buffer; + pd.nboff = skip_bits; + pd.nbits = 8 * size - unused_bits; /* 8 is CHAR_BIT from */ + if(pd.nboff > pd.nbits) + _ASN_DECODE_FAILED; + + /* + * Invoke type-specific decoder. + */ + if(!td->uper_decoder) + _ASN_DECODE_FAILED; /* PER is not compiled in */ + rval = td->uper_decoder(opt_codec_ctx, td, 0, sptr, &pd); + if(rval.code == RC_OK) { + /* Return the number of consumed bits */ + rval.consumed = ((pd.buffer - (const uint8_t *)buffer) << 3) + + pd.nboff - skip_bits; + } else { + /* PER codec is not a restartable */ + rval.consumed = 0; + } + return rval; +} + diff --git a/libs/smux/per_encoder.c b/libs/smux/per_encoder.c new file mode 100644 index 00000000..614dd233 --- /dev/null +++ b/libs/smux/per_encoder.c @@ -0,0 +1,95 @@ +#include +#include +#include + +/* Flush partially filled buffer */ +static int _uper_encode_flush_outp(asn_per_outp_t *po); + +asn_enc_rval_t +uper_encode(asn_TYPE_descriptor_t *td, void *sptr, asn_app_consume_bytes_f *cb, void *app_key) { + asn_per_outp_t po; + asn_enc_rval_t er; + + /* + * Invoke type-specific encoder. + */ + if(!td || !td->uper_encoder) + _ASN_ENCODE_FAILED; /* PER is not compiled in */ + + po.buffer = po.tmpspace; + po.nboff = 0; + po.nbits = 8 * sizeof(po.tmpspace); + po.outper = cb; + po.op_key = app_key; + po.flushed_bytes = 0; + + er = td->uper_encoder(td, 0, sptr, &po); + if(er.encoded != -1) { + size_t bits_to_flush; + + bits_to_flush = ((po.buffer - po.tmpspace) << 3) + po.nboff; + + /* Set number of bits encoded to a firm value */ + er.encoded = (po.flushed_bytes << 3) + bits_to_flush; + + if(_uper_encode_flush_outp(&po)) + _ASN_ENCODE_FAILED; + } + + return er; +} + +/* + * Argument type and callback necessary for uper_encode_to_buffer(). + */ +typedef struct enc_to_buf_arg { + void *buffer; + size_t left; +} enc_to_buf_arg; +static int encode_to_buffer_cb(const void *buffer, size_t size, void *key) { + enc_to_buf_arg *arg = (enc_to_buf_arg *)key; + + if(arg->left < size) + return -1; /* Data exceeds the available buffer size */ + + memcpy(arg->buffer, buffer, size); + arg->buffer = ((char *)arg->buffer) + size; + arg->left -= size; + + return 0; +} + +asn_enc_rval_t +uper_encode_to_buffer(asn_TYPE_descriptor_t *td, void *sptr, void *buffer, size_t buffer_size) { + enc_to_buf_arg key; + + /* + * Invoke type-specific encoder. + */ + if(!td || !td->uper_encoder) + _ASN_ENCODE_FAILED; /* PER is not compiled in */ + + key.buffer = buffer; + key.left = buffer_size; + + ASN_DEBUG("Encoding \"%s\" using UNALIGNED PER", td->name); + + return uper_encode(td, sptr, encode_to_buffer_cb, &key); +} + +static int +_uper_encode_flush_outp(asn_per_outp_t *po) { + uint8_t *buf; + + if(po->nboff == 0 && po->buffer == po->tmpspace) + return 0; + + buf = po->buffer + (po->nboff >> 3); + /* Make sure we account for the last, partially filled */ + if(po->nboff & 0x07) { + buf[0] &= 0xff << (8 - (po->nboff & 0x07)); + buf++; + } + + return po->outper(po->tmpspace, buf - po->tmpspace, po->op_key); +} diff --git a/libs/smux/per_support.c b/libs/smux/per_support.c new file mode 100644 index 00000000..c8344193 --- /dev/null +++ b/libs/smux/per_support.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2005, 2006 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * Extract a small number of bits (<= 31) from the specified PER data pointer. + */ +int32_t +per_get_few_bits(asn_per_data_t *pd, int nbits) { + size_t off; /* Next after last bit offset */ + uint32_t accum; + const uint8_t *buf; + + if(nbits < 0 || pd->nboff + nbits > pd->nbits) + return -1; + + ASN_DEBUG("[PER get %d bits from %p+%d bits]", + nbits, pd->buffer, pd->nboff); + + /* + * Normalize position indicator. + */ + if(pd->nboff >= 8) { + pd->buffer += (pd->nboff >> 3); + pd->nbits -= (pd->nboff & ~0x07); + pd->nboff &= 0x07; + } + off = (pd->nboff += nbits); + buf = pd->buffer; + + /* + * Extract specified number of bits. + */ + if(off <= 8) + accum = nbits ? (buf[0]) >> (8 - off) : 0; + else if(off <= 16) + accum = ((buf[0] << 8) + buf[1]) >> (16 - off); + else if(off <= 24) + accum = ((buf[0] << 16) + (buf[1] << 8) + buf[2]) >> (24 - off); + else if(off <= 31) + accum = ((buf[0] << 24) + (buf[1] << 16) + + (buf[2] << 8) + (buf[3])) >> (32 - off); + else if(nbits <= 31) { + asn_per_data_t tpd = *pd; + /* Here are we with our 31-bits limit plus 1..7 bits offset. */ + tpd.nboff -= nbits; + accum = per_get_few_bits(&tpd, nbits - 24) << 24; + accum |= per_get_few_bits(&tpd, 24); + } else { + pd->nboff -= nbits; /* Oops, revert back */ + return -1; + } + + return (accum & (((uint32_t)1 << nbits) - 1)); +} + +/* + * Extract a large number of bits from the specified PER data pointer. + */ +int +per_get_many_bits(asn_per_data_t *pd, uint8_t *dst, int alright, int nbits) { + int32_t value; + + if(alright && (nbits & 7)) { + /* Perform right alignment of a first few bits */ + value = per_get_few_bits(pd, nbits & 0x07); + if(value < 0) return -1; + *dst++ = value; /* value is already right-aligned */ + nbits &= ~7; + } + + while(nbits) { + if(nbits >= 24) { + value = per_get_few_bits(pd, 24); + if(value < 0) return -1; + *(dst++) = value >> 16; + *(dst++) = value >> 8; + *(dst++) = value; + nbits -= 24; + } else { + value = per_get_few_bits(pd, nbits); + if(value < 0) return -1; + if(nbits & 7) { /* implies left alignment */ + value <<= 8 - (nbits & 7), + nbits += 8 - (nbits & 7); + if(nbits > 24) + *dst++ = value >> 24; + } + if(nbits > 16) + *dst++ = value >> 16; + if(nbits > 8) + *dst++ = value >> 8; + *dst++ = value; + break; + } + } + + return 0; +} + +/* + * Get the length "n" from the stream. + */ +ssize_t +uper_get_length(asn_per_data_t *pd, int ebits, int *repeat) { + ssize_t value; + + *repeat = 0; + + if(ebits >= 0) return per_get_few_bits(pd, ebits); + + value = per_get_few_bits(pd, 8); + if(value < 0) return -1; + if((value & 128) == 0) /* #10.9.3.6 */ + return (value & 0x7F); + if((value & 64) == 0) { /* #10.9.3.7 */ + value = ((value & 63) << 8) | per_get_few_bits(pd, 8); + if(value < 0) return -1; + return value; + } + value &= 63; /* this is "m" from X.691, #10.9.3.8 */ + if(value < 1 || value > 4) + return -1; + *repeat = 1; + return (16384 * value); +} + +/* + * Get the normally small non-negative whole number. + * X.691, #10.6 + */ +ssize_t +uper_get_nsnnwn(asn_per_data_t *pd) { + ssize_t value; + + value = per_get_few_bits(pd, 7); + if(value & 64) { /* implicit (value < 0) */ + value &= 63; + value <<= 2; + value |= per_get_few_bits(pd, 2); + if(value & 128) /* implicit (value < 0) */ + return -1; + if(value == 0) + return 0; + if(value >= 3) + return -1; + value = per_get_few_bits(pd, 8 * value); + return value; + } + + return value; +} + +/* + * Put the normally small non-negative whole number. + * X.691, #10.6 + */ +int +uper_put_nsnnwn(asn_per_outp_t *po, int n) { + int bytes; + + if(n <= 63) { + if(n < 0) return -1; + return per_put_few_bits(po, n, 7); + } + if(n < 256) + bytes = 1; + else if(n < 65536) + bytes = 2; + else if(n < 256 * 65536) + bytes = 3; + else + return -1; /* This is not a "normally small" value */ + if(per_put_few_bits(po, bytes, 8)) + return -1; + + return per_put_few_bits(po, n, 8 * bytes); +} + + +/* + * Put a small number of bits (<= 31). + */ +int +per_put_few_bits(asn_per_outp_t *po, uint32_t bits, int obits) { + size_t off; /* Next after last bit offset */ + size_t omsk; /* Existing last byte meaningful bits mask */ + uint8_t *buf; + + if(obits <= 0 || obits >= 32) return obits ? -1 : 0; + + ASN_DEBUG("[PER put %d bits to %p+%d bits]", + obits, po->buffer, po->nboff); + + /* + * Normalize position indicator. + */ + if(po->nboff >= 8) { + po->buffer += (po->nboff >> 3); + po->nbits -= (po->nboff & ~0x07); + po->nboff &= 0x07; + } + + /* + * Flush whole-bytes output, if necessary. + */ + if(po->nboff + obits > po->nbits) { + int complete_bytes = (po->buffer - po->tmpspace); + if(po->outper(po->buffer, complete_bytes, po->op_key) < 0) + return -1; + if(po->nboff) + po->tmpspace[0] = po->buffer[0]; + po->buffer = po->tmpspace; + po->nbits = 8 * sizeof(po->tmpspace); + po->flushed_bytes += complete_bytes; + } + + /* + * Now, due to sizeof(tmpspace), we are guaranteed large enough space. + */ + buf = po->buffer; + omsk = ~((1 << (8 - po->nboff)) - 1); + off = (po->nboff += obits); + + /* Clear data of debris before meaningful bits */ + bits &= (((uint32_t)1 << obits) - 1); + + ASN_DEBUG("[PER out %d %u/%x (t=%d,o=%d) %x&%x=%x]", obits, bits, bits, + po->nboff - obits, off, buf[0], omsk&0xff, buf[0] & omsk); + + if(off <= 8) /* Completely within 1 byte */ + bits <<= (8 - off), + buf[0] = (buf[0] & omsk) | bits; + else if(off <= 16) + bits <<= (16 - off), + buf[0] = (buf[0] & omsk) | (bits >> 8), + buf[1] = bits; + else if(off <= 24) + bits <<= (24 - off), + buf[0] = (buf[0] & omsk) | (bits >> 16), + buf[1] = bits >> 8, + buf[2] = bits; + else if(off <= 31) + bits <<= (32 - off), + buf[0] = (buf[0] & omsk) | (bits >> 24), + buf[1] = bits >> 16, + buf[2] = bits >> 8, + buf[3] = bits; + else { + ASN_DEBUG("->[PER out split %d]", obits); + per_put_few_bits(po, bits >> 8, 24); + per_put_few_bits(po, bits, obits - 24); + ASN_DEBUG("<-[PER out split %d]", obits); + } + + ASN_DEBUG("[PER out %u/%x => %02x buf+%d]", + bits, bits, buf[0], po->buffer - po->tmpspace); + + return 0; +} + + +/* + * Output a large number of bits. + */ +int +per_put_many_bits(asn_per_outp_t *po, const uint8_t *src, int nbits) { + + while(nbits) { + uint32_t value; + + if(nbits >= 24) { + value = (src[0] << 16) | (src[1] << 8) | src[2]; + src += 3; + nbits -= 24; + if(per_put_few_bits(po, value, 24)) + return -1; + } else { + value = src[0]; + if(nbits > 8) + value = (value << 8) | src[1]; + if(nbits > 16) + value = (value << 8) | src[2]; + if(nbits & 0x07) + value >>= (8 - (nbits & 0x07)); + if(per_put_few_bits(po, value, nbits)) + return -1; + break; + } + } + + return 0; +} + +/* + * Put the length "n" (or part of it) into the stream. + */ +ssize_t +uper_put_length(asn_per_outp_t *po, size_t length) { + + if(length <= 127) /* #10.9.3.6 */ + return per_put_few_bits(po, length, 8) + ? -1 : (ssize_t)length; + else if(length < 16384) /* #10.9.3.7 */ + return per_put_few_bits(po, length|0x8000, 16) + ? -1 : (ssize_t)length; + + length >>= 14; + if(length > 4) length = 4; + + return per_put_few_bits(po, 0xC0 | length, 8) + ? -1 : (ssize_t)(length << 14); +} + diff --git a/libs/smux/xer_decoder.c b/libs/smux/xer_decoder.c new file mode 100644 index 00000000..161dc78c --- /dev/null +++ b/libs/smux/xer_decoder.c @@ -0,0 +1,363 @@ +/* + * Copyright (c) 2004, 2005 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include /* XER/XML parsing support */ + + +/* + * Decode the XER encoding of a given type. + */ +asn_dec_rval_t +xer_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, + void **struct_ptr, const void *buffer, size_t size) { + asn_codec_ctx_t s_codec_ctx; + + /* + * Stack checker requires that the codec context + * must be allocated on the stack. + */ + if(opt_codec_ctx) { + if(opt_codec_ctx->max_stack_size) { + s_codec_ctx = *opt_codec_ctx; + opt_codec_ctx = &s_codec_ctx; + } + } else { + /* If context is not given, be security-conscious anyway */ + memset(&s_codec_ctx, 0, sizeof(s_codec_ctx)); + s_codec_ctx.max_stack_size = _ASN_DEFAULT_STACK_MAX; + opt_codec_ctx = &s_codec_ctx; + } + + /* + * Invoke type-specific decoder. + */ + return td->xer_decoder(opt_codec_ctx, td, struct_ptr, 0, buffer, size); +} + + + +struct xer__cb_arg { + pxml_chunk_type_e chunk_type; + size_t chunk_size; + const void *chunk_buf; + int callback_not_invoked; +}; + +static int +xer__token_cb(pxml_chunk_type_e type, const void *_chunk_data, size_t _chunk_size, void *key) { + struct xer__cb_arg *arg = (struct xer__cb_arg *)key; + arg->chunk_type = type; + arg->chunk_size = _chunk_size; + arg->chunk_buf = _chunk_data; + arg->callback_not_invoked = 0; + return -1; /* Terminate the XML parsing */ +} + +/* + * Fetch the next token from the XER/XML stream. + */ +ssize_t +xer_next_token(int *stateContext, const void *buffer, size_t size, pxer_chunk_type_e *ch_type) { + struct xer__cb_arg arg; + int new_stateContext = *stateContext; + ssize_t ret; + + arg.callback_not_invoked = 1; + ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg); + if(ret < 0) return -1; + if(arg.callback_not_invoked) { + assert(ret == 0); /* No data was consumed */ + return 0; /* Try again with more data */ + } else { + assert(arg.chunk_size); + assert(arg.chunk_buf == buffer); + } + + /* + * Translate the XML chunk types into more convenient ones. + */ + switch(arg.chunk_type) { + case PXML_TEXT: + *ch_type = PXER_TEXT; + break; + case PXML_TAG: return 0; /* Want more */ + case PXML_TAG_END: + *ch_type = PXER_TAG; + break; + case PXML_COMMENT: + case PXML_COMMENT_END: + *ch_type = PXER_COMMENT; + break; + } + + *stateContext = new_stateContext; + return arg.chunk_size; +} + +#define CSLASH 0x2f /* '/' */ +#define LANGLE 0x3c /* '<' */ +#define RANGLE 0x3e /* '>' */ + +xer_check_tag_e +xer_check_tag(const void *buf_ptr, int size, const char *need_tag) { + const char *buf = (const char *)buf_ptr; + const char *end; + xer_check_tag_e ct = XCT_OPENING; + + if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) { + if(size >= 2) + ASN_DEBUG("Broken XML tag: \"%c...%c\"", buf[0], buf[size - 1]); + return XCT_BROKEN; + } + + /* + * Determine the tag class. + */ + if(buf[1] == CSLASH) { + buf += 2; /* advance past "" */ + ct = XCT_CLOSING; + if(size > 0 && buf[size-1] == CSLASH) + return XCT_BROKEN; /* */ + } else { + buf++; /* advance past "<" */ + size -= 2; /* strip "<" and ">" */ + if(size > 0 && buf[size-1] == CSLASH) { + ct = XCT_BOTH; + size--; /* One more, for "/" */ + } + } + + /* Sometimes we don't care about the tag */ + if(!need_tag || !*need_tag) + return (xer_check_tag_e)(XCT__UNK__MASK | ct); + + /* + * Determine the tag name. + */ + for(end = buf + size; buf < end; buf++, need_tag++) { + int b = *buf, n = *need_tag; + if(b != n) { + if(n == 0) { + switch(b) { + case 0x09: case 0x0a: case 0x0c: case 0x0d: + case 0x20: + /* "": whitespace is normal */ + return ct; + } + } + return (xer_check_tag_e)(XCT__UNK__MASK | ct); + } + if(b == 0) + return XCT_BROKEN; /* Embedded 0 in buf?! */ + } + if(*need_tag) + return (xer_check_tag_e)(XCT__UNK__MASK | ct); + + return ct; +} + + +#undef ADVANCE +#define ADVANCE(num_bytes) do { \ + size_t num = (num_bytes); \ + buf_ptr = ((const char *)buf_ptr) + num; \ + size -= num; \ + consumed_myself += num; \ + } while(0) + +#undef RETURN +#define RETURN(_code) do { \ + rval.code = _code; \ + rval.consumed = consumed_myself; \ + if(rval.code != RC_OK) \ + ASN_DEBUG("Failed with %d", rval.code); \ + return rval; \ + } while(0) + +#define XER_GOT_BODY(chunk_buf, chunk_size, size) do { \ + ssize_t converted_size = body_receiver \ + (struct_key, chunk_buf, chunk_size, \ + (size_t)chunk_size < size); \ + if(converted_size == -1) RETURN(RC_FAIL); \ + if(converted_size == 0 \ + && size == (size_t)chunk_size) \ + RETURN(RC_WMORE); \ + chunk_size = converted_size; \ + } while(0) +#define XER_GOT_EMPTY() do { \ + if(body_receiver(struct_key, 0, 0, size > 0) == -1) \ + RETURN(RC_FAIL); \ + } while(0) + +/* + * Generalized function for decoding the primitive values. + */ +asn_dec_rval_t +xer_decode_general(asn_codec_ctx_t *opt_codec_ctx, + asn_struct_ctx_t *ctx, /* Type decoder context */ + void *struct_key, + const char *xml_tag, /* Expected XML tag */ + const void *buf_ptr, size_t size, + int (*opt_unexpected_tag_decoder) + (void *struct_key, const void *chunk_buf, size_t chunk_size), + ssize_t (*body_receiver) + (void *struct_key, const void *chunk_buf, size_t chunk_size, + int have_more) + ) { + + asn_dec_rval_t rval; + ssize_t consumed_myself = 0; + + (void)opt_codec_ctx; + + /* + * Phases of XER/XML processing: + * Phase 0: Check that the opening tag matches our expectations. + * Phase 1: Processing body and reacting on closing tag. + */ + if(ctx->phase > 1) RETURN(RC_FAIL); + for(;;) { + pxer_chunk_type_e ch_type; /* XER chunk type */ + ssize_t ch_size; /* Chunk size */ + xer_check_tag_e tcv; /* Tag check value */ + + /* + * Get the next part of the XML stream. + */ + ch_size = xer_next_token(&ctx->context, buf_ptr, size, + &ch_type); + switch(ch_size) { + case -1: RETURN(RC_FAIL); + case 0: + RETURN(RC_WMORE); + default: + switch(ch_type) { + case PXER_COMMENT: /* Got XML comment */ + ADVANCE(ch_size); /* Skip silently */ + continue; + case PXER_TEXT: + if(ctx->phase == 0) { + /* + * We have to ignore whitespace here, + * but in order to be forward compatible + * with EXTENDED-XER (EMBED-VALUES, #25) + * any text is just ignored here. + */ + } else { + XER_GOT_BODY(buf_ptr, ch_size, size); + } + ADVANCE(ch_size); + continue; + case PXER_TAG: + break; /* Check the rest down there */ + } + } + + assert(ch_type == PXER_TAG && size); + + tcv = xer_check_tag(buf_ptr, ch_size, xml_tag); + /* + * Phase 0: + * Expecting the opening tag + * for the type being processed. + * Phase 1: + * Waiting for the closing XML tag. + */ + switch(tcv) { + case XCT_BOTH: + if(ctx->phase) break; + /* Finished decoding of an empty element */ + XER_GOT_EMPTY(); + ADVANCE(ch_size); + ctx->phase = 2; /* Phase out */ + RETURN(RC_OK); + case XCT_OPENING: + if(ctx->phase) break; + ADVANCE(ch_size); + ctx->phase = 1; /* Processing body phase */ + continue; + case XCT_CLOSING: + if(!ctx->phase) break; + ADVANCE(ch_size); + ctx->phase = 2; /* Phase out */ + RETURN(RC_OK); + case XCT_UNKNOWN_BO: + /* + * Certain tags in the body may be expected. + */ + if(opt_unexpected_tag_decoder + && opt_unexpected_tag_decoder(struct_key, + buf_ptr, ch_size) >= 0) { + /* Tag's processed fine */ + ADVANCE(ch_size); + if(!ctx->phase) { + /* We are not expecting + * the closing tag anymore. */ + ctx->phase = 2; /* Phase out */ + RETURN(RC_OK); + } + continue; + } + /* Fall through */ + default: + break; /* Unexpected tag */ + } + + ASN_DEBUG("Unexpected XML tag (expected \"%s\")", xml_tag); + break; /* Dark and mysterious things have just happened */ + } + + RETURN(RC_FAIL); +} + + +int +xer_is_whitespace(const void *chunk_buf, size_t chunk_size) { + const char *p = (const char *)chunk_buf; + const char *pend = p + chunk_size; + + for(; p < pend; p++) { + switch(*p) { + /* X.693, #8.1.4 + * HORISONTAL TAB (9) + * LINE FEED (10) + * CARRIAGE RETURN (13) + * SPACE (32) + */ + case 0x09: case 0x0a: case 0x0d: case 0x20: + break; + default: + return 0; + } + } + return 1; /* All whitespace */ +} + +/* + * This is a vastly simplified, non-validating XML tree skipper. + */ +int +xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) { + assert(*depth > 0); + switch(tcv) { + case XCT_BOTH: + case XCT_UNKNOWN_BO: + /* These negate each other. */ + return 0; + case XCT_OPENING: + case XCT_UNKNOWN_OP: + ++(*depth); + return 0; + case XCT_CLOSING: + case XCT_UNKNOWN_CL: + if(--(*depth) == 0) + return (tcv == XCT_CLOSING) ? 2 : 1; + return 0; + default: + return -1; + } +} diff --git a/libs/smux/xer_encoder.c b/libs/smux/xer_encoder.c new file mode 100644 index 00000000..aa7cf040 --- /dev/null +++ b/libs/smux/xer_encoder.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2003, 2004 Lev Walkin . All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include +#include + +/* + * The XER encoder of any type. May be invoked by the application. + */ +asn_enc_rval_t +xer_encode(asn_TYPE_descriptor_t *td, void *sptr, + enum xer_encoder_flags_e xer_flags, + asn_app_consume_bytes_f *cb, void *app_key) { + asn_enc_rval_t er, tmper; + const char *mname; + size_t mlen; + int xcan = (xer_flags & XER_F_CANONICAL) ? 1 : 2; + + if(!td || !sptr) goto cb_failed; + + mname = td->xml_tag; + mlen = strlen(mname); + + _ASN_CALLBACK3("<", 1, mname, mlen, ">", 1); + + tmper = td->xer_encoder(td, sptr, 1, xer_flags, cb, app_key); + if(tmper.encoded == -1) return tmper; + + _ASN_CALLBACK3("\n", xcan); + + er.encoded = 4 + xcan + (2 * mlen) + tmper.encoded; + + _ASN_ENCODED_OK(er); +cb_failed: + _ASN_ENCODE_FAILED; +} + +/* + * This is a helper function for xer_fprint, which directs all incoming data + * into the provided file descriptor. + */ +static int +xer__print2fp(const void *buffer, size_t size, void *app_key) { + FILE *stream = (FILE *)app_key; + + if(fwrite(buffer, 1, size, stream) != size) + return -1; + + return 0; +} + +int +xer_fprint(FILE *stream, asn_TYPE_descriptor_t *td, void *sptr) { + asn_enc_rval_t er; + + if(!stream) stream = stdout; + if(!td || !sptr) + return -1; + + er = xer_encode(td, sptr, XER_F_BASIC, xer__print2fp, stream); + if(er.encoded == -1) + return -1; + + return fflush(stream); +} diff --git a/libs/smux/xer_support.c b/libs/smux/xer_support.c new file mode 100644 index 00000000..9e34e692 --- /dev/null +++ b/libs/smux/xer_support.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2003, 2004 X/IO Labs, xiolabs.com. + * Copyright (c) 2003, 2004, 2005 Lev Walkin . + * All rights reserved. + * Redistribution and modifications are permitted subject to BSD license. + */ +#include +#include + +/* Parser states */ +typedef enum { + ST_TEXT, + ST_TAG_START, + ST_TAG_BODY, + ST_TAG_QUOTE_WAIT, + ST_TAG_QUOTED_STRING, + ST_TAG_UNQUOTED_STRING, + ST_COMMENT_WAIT_DASH1, /* ""[0] */ + ST_COMMENT_CLO_RT /* "-->"[1] */ +} pstate_e; + +static pxml_chunk_type_e final_chunk_type[] = { + PXML_TEXT, + PXML_TAG_END, + PXML_COMMENT_END, + PXML_TAG_END, + PXML_COMMENT_END, +}; + + +static int +_charclass[256] = { + 0,0,0,0,0,0,0,0, 0,1,1,0,1,1,0,0, + 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 1,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, + 2,2,2,2,2,2,2,2, 2,2,0,0,0,0,0,0, /* 01234567 89 */ + 0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, /* ABCDEFG HIJKLMNO */ + 3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0, /* PQRSTUVW XYZ */ + 0,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, /* abcdefg hijklmno */ + 3,3,3,3,3,3,3,3, 3,3,3,0,0,0,0,0 /* pqrstuvw xyz */ +}; +#define WHITESPACE(c) (_charclass[(unsigned char)(c)] == 1) +#define ALNUM(c) (_charclass[(unsigned char)(c)] >= 2) +#define ALPHA(c) (_charclass[(unsigned char)(c)] == 3) + +/* Aliases for characters, ASCII/UTF-8 */ +#define EXCLAM 0x21 /* '!' */ +#define CQUOTE 0x22 /* '"' */ +#define CDASH 0x2d /* '-' */ +#define CSLASH 0x2f /* '/' */ +#define LANGLE 0x3c /* '<' */ +#define CEQUAL 0x3d /* '=' */ +#define RANGLE 0x3e /* '>' */ +#define CQUEST 0x3f /* '?' */ + +/* Invoke token callback */ +#define TOKEN_CB_CALL(type, _ns, _current_too, _final) do { \ + int _ret; \ + pstate_e ns = _ns; \ + ssize_t _sz = (p - chunk_start) + _current_too; \ + if (!_sz) { \ + /* Shortcut */ \ + state = _ns; \ + break; \ + } \ + _ret = cb(type, chunk_start, _sz, key); \ + if(_ret < _sz) { \ + if(_current_too && _ret == -1) \ + state = ns; \ + goto finish; \ + } \ + chunk_start = p + _current_too; \ + state = ns; \ + } while(0) + +#define TOKEN_CB(_type, _ns, _current_too) \ + TOKEN_CB_CALL(_type, _ns, _current_too, 0) + +#define TOKEN_CB_FINAL(_type, _ns, _current_too) \ + TOKEN_CB_CALL(final_chunk_type[_type], _ns, _current_too, 1) + +/* + * Parser itself + */ +ssize_t pxml_parse(int *stateContext, const void *xmlbuf, size_t size, pxml_callback_f *cb, void *key) { + pstate_e state = (pstate_e)*stateContext; + const char *chunk_start = (const char *)xmlbuf; + const char *p = chunk_start; + const char *end = p + size; + + for(; p < end; p++) { + int C = *(const unsigned char *)p; + switch(state) { + case ST_TEXT: + /* + * Initial state: we're in the middle of some text, + * or just have started. + */ + if (C == LANGLE) + /* We're now in the tag, probably */ + TOKEN_CB(PXML_TEXT, ST_TAG_START, 0); + break; + case ST_TAG_START: + if (ALPHA(C) || (C == CSLASH)) + state = ST_TAG_BODY; + else if (C == EXCLAM) + state = ST_COMMENT_WAIT_DASH1; + else + /* + * Not characters and not whitespace. + * Must be something like "3 < 4". + */ + TOKEN_CB(PXML_TEXT, ST_TEXT, 1);/* Flush as data */ + break; + case ST_TAG_BODY: + switch(C) { + case RANGLE: + /* End of the tag */ + TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1); + break; + case LANGLE: + /* + * The previous tag wasn't completed, but still + * recognized as valid. (Mozilla-compatible) + */ + TOKEN_CB_FINAL(PXML_TAG, ST_TAG_START, 0); + break; + case CEQUAL: + state = ST_TAG_QUOTE_WAIT; + break; + } + break; + case ST_TAG_QUOTE_WAIT: + /* + * State after the equal sign ("=") in the tag. + */ + switch(C) { + case CQUOTE: + state = ST_TAG_QUOTED_STRING; + break; + case RANGLE: + /* End of the tag */ + TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1); + break; + default: + if(!WHITESPACE(C)) + /* Unquoted string value */ + state = ST_TAG_UNQUOTED_STRING; + } + break; + case ST_TAG_QUOTED_STRING: + /* + * Tag attribute's string value in quotes. + */ + if(C == CQUOTE) { + /* Return back to the tag state */ + state = ST_TAG_BODY; + } + break; + case ST_TAG_UNQUOTED_STRING: + if(C == RANGLE) { + /* End of the tag */ + TOKEN_CB_FINAL(PXML_TAG, ST_TEXT, 1); + } else if(WHITESPACE(C)) { + /* Return back to the tag state */ + state = ST_TAG_BODY; + } + break; + case ST_COMMENT_WAIT_DASH1: + if(C == CDASH) { + state = ST_COMMENT_WAIT_DASH2; + } else { + /* Some ordinary tag. */ + state = ST_TAG_BODY; + } + break; + case ST_COMMENT_WAIT_DASH2: + if(C == CDASH) { + /* Seen "<--" */ + state = ST_COMMENT; + } else { + /* Some ordinary tag */ + state = ST_TAG_BODY; + } + break; + case ST_COMMENT: + if(C == CDASH) { + state = ST_COMMENT_CLO_DASH2; + } + break; + case ST_COMMENT_CLO_DASH2: + if(C == CDASH) { + state = ST_COMMENT_CLO_RT; + } else { + /* This is not an end of a comment */ + state = ST_COMMENT; + } + break; + case ST_COMMENT_CLO_RT: + if(C == RANGLE) { + TOKEN_CB_FINAL(PXML_COMMENT, ST_TEXT, 1); + } else if(C == CDASH) { + /* Maintain current state, still waiting for '>' */ + } else { + state = ST_COMMENT; + } + break; + } /* switch(*ptr) */ + } /* for() */ + + /* + * Flush the partially processed chunk, state permitting. + */ + if(p - chunk_start) { + switch (state) { + case ST_COMMENT: + TOKEN_CB(PXML_COMMENT, state, 0); + break; + case ST_TEXT: + TOKEN_CB(PXML_TEXT, state, 0); + break; + default: break; /* a no-op */ + } + } + +finish: + *stateContext = (int)state; + return chunk_start - (const char *)xmlbuf; +} + diff --git a/libs/srvconf/CMakeLists.txt b/libs/srvconf/CMakeLists.txt new file mode 100644 index 00000000..e3cc91bb --- /dev/null +++ b/libs/srvconf/CMakeLists.txt @@ -0,0 +1,8 @@ +set ( CPP_FILES netunit.cpp servconf.cpp ) +file ( GLOB PARSERS parsers/*.cpp ) + +add_library ( srvconf STATIC ${CPP_FILES} ${PARSERS} ) + +target_include_directories ( srvconf PUBLIC include ) + +target_link_libraries ( srvconf crypto common ) diff --git a/libs/srvconf/Makefile b/libs/srvconf/Makefile new file mode 100644 index 00000000..d7bc80c0 --- /dev/null +++ b/libs/srvconf/Makefile @@ -0,0 +1,35 @@ +############################################################################### +# $Id: Makefile,v 1.9 2010/08/18 07:47:03 faust Exp $ +############################################################################### + +LIB_NAME = stgsrvconf + +STGLIBS = -lstgcommon \ + -lstgcrypto +LIBS = -lexpat + +SRCS = parsers/property.cpp \ + parsers/simple.cpp \ + parsers/server_info.cpp \ + parsers/get_admin.cpp \ + parsers/chg_admin.cpp \ + parsers/get_tariff.cpp \ + parsers/chg_tariff.cpp \ + parsers/auth_by.cpp \ + parsers/get_user.cpp \ + parsers/chg_user.cpp \ + parsers/get_service.cpp \ + parsers/chg_service.cpp \ + parsers/get_corp.cpp \ + parsers/chg_corp.cpp \ + netunit.cpp \ + servconf.cpp + + +INCS = servconf.h \ + netunit.h + +LIB_INCS = -I ../common.lib/include \ + -I ../crypto.lib/include + +include ../Makefile.in diff --git a/libs/srvconf/include/stg/servconf.h b/libs/srvconf/include/stg/servconf.h new file mode 100644 index 00000000..efdf4b6b --- /dev/null +++ b/libs/srvconf/include/stg/servconf.h @@ -0,0 +1,111 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SERVCONF_H__ +#define __STG_STGLIBS_SERVCONF_H__ + +#include "stg/servconf_types.h" + +#include "stg/admin_conf.h" + +#include +#include + +struct USER_CONF_RES; +struct USER_STAT_RES; +struct TARIFF_DATA_RES; +struct SERVICE_CONF_RES; +struct CORP_CONF_RES; + +namespace STG +{ + +class SERVCONF +{ +public: + SERVCONF(const std::string & server, uint16_t port, + const std::string & login, const std::string & password); + SERVCONF(const std::string & server, uint16_t port, + const std::string & localAddress, uint16_t localPort, + const std::string & login, const std::string & password); + ~SERVCONF(); + + int ServerInfo(SERVER_INFO::CALLBACK f, void * data); + + int RawXML(const std::string & request, RAW_XML::CALLBACK f, void * data); + + int GetAdmins(GET_CONTAINER::CALLBACK::TYPE f, void * data); + int GetAdmin(const std::string & login, GET_ADMIN::CALLBACK f, void * data); + int ChgAdmin(const ADMIN_CONF_RES & conf, SIMPLE::CALLBACK f, void * data); + int AddAdmin(const std::string & login, + const ADMIN_CONF_RES & conf, + SIMPLE::CALLBACK f, void * data); + int DelAdmin(const std::string & login, SIMPLE::CALLBACK f, void * data); + + int GetTariffs(GET_CONTAINER::CALLBACK::TYPE f, void * data); + int GetTariff(const std::string & name, GET_TARIFF::CALLBACK f, void * data); + int ChgTariff(const TARIFF_DATA_RES & conf, SIMPLE::CALLBACK f, void * data); + int AddTariff(const std::string & name, + const TARIFF_DATA_RES & conf, + SIMPLE::CALLBACK f, void * data); + int DelTariff(const std::string & name, SIMPLE::CALLBACK f, void * data); + + int GetUsers(GET_CONTAINER::CALLBACK::TYPE f, void * data); + int GetUser(const std::string & login, GET_USER::CALLBACK f, void * data); + int ChgUser(const std::string & login, + const USER_CONF_RES & conf, + const USER_STAT_RES & stat, + SIMPLE::CALLBACK f, void * data); + int DelUser(const std::string & login, SIMPLE::CALLBACK f, void * data); + int AddUser(const std::string & login, + const USER_CONF_RES & conf, + const USER_STAT_RES & stat, + SIMPLE::CALLBACK f, void * data); + int AuthBy(const std::string & login, AUTH_BY::CALLBACK f, void * data); + int SendMessage(const std::string & login, const std::string & text, SIMPLE::CALLBACK f, void * data); + int CheckUser(const std::string & login, const std::string & password, SIMPLE::CALLBACK f, void * data); + + int GetServices(GET_CONTAINER::CALLBACK::TYPE f, void * data); + int GetService(const std::string & name, GET_SERVICE::CALLBACK f, void * data); + int ChgService(const SERVICE_CONF_RES & conf, SIMPLE::CALLBACK f, void * data); + int AddService(const std::string & name, + const SERVICE_CONF_RES & conf, + SIMPLE::CALLBACK f, void * data); + int DelService(const std::string & name, SIMPLE::CALLBACK f, void * data); + + int GetCorporations(GET_CONTAINER::CALLBACK::TYPE f, void * data); + int GetCorp(const std::string & name, GET_CORP::CALLBACK f, void * data); + int ChgCorp(const CORP_CONF_RES & conf, SIMPLE::CALLBACK f, void * data); + int AddCorp(const std::string & name, + const CORP_CONF_RES & conf, + SIMPLE::CALLBACK f, void * data); + int DelCorp(const std::string & name, SIMPLE::CALLBACK f, void * data); + + const std::string & GetStrError() const; + +private: + class IMPL; + IMPL * pImpl; +}; + +} // namespace STG + +#endif diff --git a/libs/srvconf/include/stg/servconf_types.h b/libs/srvconf/include/stg/servconf_types.h new file mode 100644 index 00000000..6c01d341 --- /dev/null +++ b/libs/srvconf/include/stg/servconf_types.h @@ -0,0 +1,189 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_TYPES_H__ +#define __STG_STGLIBS_SRVCONF_TYPES_H__ + +#include "stg/array.h" +#include "stg/const.h" // DIR_NUM + +#include +#include +#include +#include + +struct ADMIN_CONF; +struct TARIFF_DATA; +struct SERVICE_CONF; +struct CORP_CONF; + +namespace STG +{ + +enum status +{ +st_ok = 0, +st_conn_fail, +st_send_fail, +st_recv_fail, +st_header_err, +st_login_err, +st_logins_err, +st_data_err, +st_unknown_err, +st_dns_err, +st_xml_parse_error, +st_data_error +}; + +namespace SIMPLE +{ + +typedef void (* CALLBACK)(bool result, const std::string & reason, void * data); + +} // namespace SIMPLE + +namespace GET_CONTAINER +{ + +template +struct CALLBACK +{ +typedef void (* TYPE)(bool result, const std::string & reason, const std::vector & info, void * data); +}; + +} // namespace GET_CONTAINER + +namespace AUTH_BY +{ + +typedef std::vector INFO; +typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + +} // namespace AUTH_BY + +namespace SERVER_INFO +{ + +struct INFO +{ + std::string version; + int tariffNum; + int tariffType; + int usersNum; + std::string uname; + int dirNum; + ARRAY dirName; +}; +typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + +} // namespace SERVER_INFO + +namespace RAW_XML +{ + +typedef void (* CALLBACK)(bool result, const std::string & reason, const std::string & response, void * data); + +} // namespace RAW_XML + +namespace GET_USER +{ + +struct STAT +{ + ARRAY su; + ARRAY sd; + ARRAY mu; + ARRAY md; +}; + +struct INFO +{ + std::string login; + std::string password; + double cash; + double credit; + time_t creditExpire; + double lastCashAdd; + double lastCashAddTime; + time_t lastTimeCash; + double prepaidTraff; + int disabled; + int passive; + int disableDetailStat; + int connected; + int alwaysOnline; + uint32_t ip; + std::string ips; + std::string tariff; + std::string group; + std::string note; + std::string email; + std::string name; + std::string address; + std::string phone; + std::string corp; + STAT stat; + time_t pingTime; + time_t lastActivityTime; + ARRAY userData; + std::vector services; + std::vector authBy; +}; + +typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + +} // namespace GET_USER + +namespace GET_ADMIN +{ + +typedef ADMIN_CONF INFO; +typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + +} // namespace GET_ADMIN + +namespace GET_TARIFF +{ + +typedef TARIFF_DATA INFO; +typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + +} // namespace GET_TARIFF + +namespace GET_SERVICE +{ + +typedef SERVICE_CONF INFO; +typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + +} // namespace GET_SERVICE + +namespace GET_CORP +{ + +typedef CORP_CONF INFO; +typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + +} // namespace GET_CORP + +} // namespace STG + +#endif diff --git a/libs/srvconf/netunit.cpp b/libs/srvconf/netunit.cpp new file mode 100644 index 00000000..65151587 --- /dev/null +++ b/libs/srvconf/netunit.cpp @@ -0,0 +1,404 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + */ + +#include "netunit.h" + +#include "stg/servconf_types.h" +#include "stg/common.h" +#include "stg/blowfish.h" +#include "stg/bfstream.h" + +#include // std::min + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +const char STG_HEADER[] = "SG04"; +const char OK_HEADER[] = "OKHD"; +const char ERR_HEADER[] = "ERHD"; +const char OK_LOGIN[] = "OKLG"; +const char ERR_LOGIN[] = "ERLG"; +const char OK_LOGINS[] = "OKLS"; +const char ERR_LOGINS[] = "ERLS"; + +using namespace STG; + +namespace +{ + +struct ReadState +{ + bool final; + NETTRANSACT::CALLBACK callback; + void * callbackData; + NETTRANSACT * nt; +}; + +} + +//--------------------------------------------------------------------------- + +const char SEND_DATA_ERROR[] = "Error sending data."; +const char RECV_DATA_ANSWER_ERROR[] = "Error receiving data answer."; +const char UNKNOWN_ERROR[] = "Unknown error"; +const char CONNECT_FAILED[] = "Failed to connect."; +const char BIND_FAILED[] = "Failed to bind."; +const char INCORRECT_LOGIN[] = "Incorrect login."; +const char INCORRECT_HEADER[] = "Incorrect header."; +const char SEND_LOGIN_ERROR[] = "Error sending login."; +const char RECV_LOGIN_ANSWER_ERROR[] = "Error receiving login answer."; +const char CREATE_SOCKET_ERROR[] = "Failed to create socket."; +const char SEND_HEADER_ERROR[] = "Error sending header."; +const char RECV_HEADER_ANSWER_ERROR[] = "Error receiving header answer."; + +//--------------------------------------------------------------------------- +NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p, + const std::string & l, const std::string & pwd) + : server(s), + port(p), + localPort(0), + login(l), + password(pwd), + sock(-1) +{ +} +//--------------------------------------------------------------------------- +NETTRANSACT::NETTRANSACT(const std::string & s, uint16_t p, + const std::string & la, uint16_t lp, + const std::string & l, const std::string & pwd) + : server(s), + port(p), + localAddress(la), + localPort(lp), + login(l), + password(pwd), + sock(-1) +{ +} +//--------------------------------------------------------------------------- +NETTRANSACT::~NETTRANSACT() +{ +Disconnect(); +} +//--------------------------------------------------------------------------- +int NETTRANSACT::Connect() +{ +sock = socket(PF_INET, SOCK_STREAM, 0); +if (sock < 0) + { + errorMsg = CREATE_SOCKET_ERROR; + return st_conn_fail; + } + +if (!localAddress.empty()) + { + if (localPort == 0) + localPort = port; + + unsigned long ip = inet_addr(localAddress.c_str()); + + if (ip == INADDR_NONE) + { + struct hostent * phe = gethostbyname(localAddress.c_str()); + if (phe == NULL) + { + errorMsg = "Can not reslove '" + localAddress + "'"; + return st_dns_err; + } + + struct hostent he; + memcpy(&he, phe, sizeof(he)); + ip = *((long *)he.h_addr_list[0]); + } + + struct sockaddr_in localAddr; + memset(&localAddr, 0, sizeof(localAddr)); + localAddr.sin_family = AF_INET; + localAddr.sin_port = htons(localPort); + localAddr.sin_addr.s_addr = ip; + + if (bind(sock, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) + { + errorMsg = BIND_FAILED; + return st_conn_fail; + } + } + +struct sockaddr_in outerAddr; +memset(&outerAddr, 0, sizeof(outerAddr)); + +unsigned long ip = inet_addr(server.c_str()); + +if (ip == INADDR_NONE) + { + struct hostent * phe = gethostbyname(server.c_str()); + if (phe == NULL) + { + errorMsg = "Can not reslove '" + server + "'"; + return st_dns_err; + } + + struct hostent he; + memcpy(&he, phe, sizeof(he)); + ip = *((long *)he.h_addr_list[0]); + } + +outerAddr.sin_family = AF_INET; +outerAddr.sin_port = htons(port); +outerAddr.sin_addr.s_addr = ip; + +if (connect(sock, (struct sockaddr *)&outerAddr, sizeof(outerAddr)) < 0) + { + errorMsg = CONNECT_FAILED; + return st_conn_fail; + } + +return st_ok; +} +//--------------------------------------------------------------------------- +void NETTRANSACT::Disconnect() +{ +if (sock != -1) + { + shutdown(sock, SHUT_RDWR); + close(sock); + sock = -1; + } +} +//--------------------------------------------------------------------------- +int NETTRANSACT::Transact(const std::string & request, CALLBACK callback, void * data) +{ +int ret; +if ((ret = TxHeader()) != st_ok) + return ret; + +if ((ret = RxHeaderAnswer()) != st_ok) + return ret; + +if ((ret = TxLogin()) != st_ok) + return ret; + +if ((ret = RxLoginAnswer()) != st_ok) + return ret; + +if ((ret = TxLoginS()) != st_ok) + return ret; + +if ((ret = RxLoginSAnswer()) != st_ok) + return ret; + +if ((ret = TxData(request)) != st_ok) + return ret; + +if ((ret = RxDataAnswer(callback, data)) != st_ok) + return ret; + +return st_ok; +} +//--------------------------------------------------------------------------- +int NETTRANSACT::TxHeader() +{ +if (!WriteAll(sock, STG_HEADER, strlen(STG_HEADER))) + { + errorMsg = SEND_HEADER_ERROR; + return st_send_fail; + } + +return st_ok; +} +//--------------------------------------------------------------------------- +int NETTRANSACT::RxHeaderAnswer() +{ +char buffer[sizeof(STG_HEADER) + 1]; + +if (!ReadAll(sock, buffer, strlen(OK_HEADER))) + { + errorMsg = RECV_HEADER_ANSWER_ERROR; + return st_recv_fail; + } + +if (strncmp(OK_HEADER, buffer, strlen(OK_HEADER)) == 0) + return st_ok; + +if (strncmp(ERR_HEADER, buffer, strlen(ERR_HEADER)) == 0) + { + errorMsg = INCORRECT_HEADER; + return st_header_err; + } +else + { + errorMsg = UNKNOWN_ERROR; + return st_unknown_err; + } +} +//--------------------------------------------------------------------------- +int NETTRANSACT::TxLogin() +{ +char loginZ[ADM_LOGIN_LEN + 1]; +memset(loginZ, 0, ADM_LOGIN_LEN + 1); +strncpy(loginZ, login.c_str(), ADM_LOGIN_LEN); + +if (!WriteAll(sock, loginZ, ADM_LOGIN_LEN)) + { + errorMsg = SEND_LOGIN_ERROR; + return st_send_fail; + } + +return st_ok; +} +//--------------------------------------------------------------------------- +int NETTRANSACT::RxLoginAnswer() +{ +char buffer[sizeof(OK_LOGIN) + 1]; + +if (!ReadAll(sock, buffer, strlen(OK_LOGIN))) + { + errorMsg = RECV_LOGIN_ANSWER_ERROR; + return st_recv_fail; + } + +if (strncmp(OK_LOGIN, buffer, strlen(OK_LOGIN)) == 0) + return st_ok; + +if (strncmp(ERR_LOGIN, buffer, strlen(ERR_LOGIN)) == 0) + { + errorMsg = INCORRECT_LOGIN; + return st_login_err; + } +else + { + errorMsg = UNKNOWN_ERROR; + return st_unknown_err; + } +} +//--------------------------------------------------------------------------- +int NETTRANSACT::TxLoginS() +{ +char loginZ[ADM_LOGIN_LEN + 1]; +memset(loginZ, 0, ADM_LOGIN_LEN + 1); + +BLOWFISH_CTX ctx; +InitContext(password.c_str(), PASSWD_LEN, &ctx); +EncryptString(loginZ, login.c_str(), std::min(login.length() + 1, ADM_LOGIN_LEN), &ctx); +if (!WriteAll(sock, loginZ, ADM_LOGIN_LEN)) + { + errorMsg = SEND_LOGIN_ERROR; + return st_send_fail; + } + +return st_ok; +} +//--------------------------------------------------------------------------- +int NETTRANSACT::RxLoginSAnswer() +{ +char buffer[sizeof(OK_LOGINS) + 1]; + +if (!ReadAll(sock, buffer, strlen(OK_LOGINS))) + { + errorMsg = RECV_LOGIN_ANSWER_ERROR; + return st_recv_fail; + } + +if (strncmp(OK_LOGINS, buffer, strlen(OK_LOGINS)) == 0) + return st_ok; + +if (strncmp(ERR_LOGINS, buffer, strlen(ERR_LOGINS)) == 0) + { + errorMsg = INCORRECT_LOGIN; + return st_logins_err; + } +else + { + errorMsg = UNKNOWN_ERROR; + return st_unknown_err; + } +} +//--------------------------------------------------------------------------- +int NETTRANSACT::TxData(const std::string & text) +{ +STG::ENCRYPT_STREAM stream(password, TxCrypto, this); +stream.Put(text.c_str(), text.length() + 1, true); +if (!stream.IsOk()) + { + errorMsg = SEND_DATA_ERROR; + return st_send_fail; + } + +return st_ok; +} +//--------------------------------------------------------------------------- +int NETTRANSACT::RxDataAnswer(CALLBACK callback, void * data) +{ +ReadState state = {false, callback, data, this}; +STG::DECRYPT_STREAM stream(password, RxCrypto, &state); +while (!state.final) + { + char buffer[1024]; + ssize_t res = read(sock, buffer, sizeof(buffer)); + if (res < 0) + { + errorMsg = RECV_DATA_ANSWER_ERROR; + return st_recv_fail; + } + stream.Put(buffer, res, res == 0); + if (!stream.IsOk()) + return st_xml_parse_error; + } + +return st_ok; +} +//--------------------------------------------------------------------------- +bool NETTRANSACT::TxCrypto(const void * block, size_t size, void * data) +{ +assert(data != NULL); +NETTRANSACT & nt = *static_cast(data); +if (!WriteAll(nt.sock, block, size)) + return false; +return true; +} +//--------------------------------------------------------------------------- +bool NETTRANSACT::RxCrypto(const void * block, size_t size, void * data) +{ +assert(data != NULL); +ReadState & state = *static_cast(data); + +const char * buffer = static_cast(block); +for (size_t pos = 0; pos < size; ++pos) + if (buffer[pos] == 0) + { + state.final = true; + size = pos; // Adjust string size + } + +if (state.callback) + if (!state.callback(std::string(buffer, size), state.final, state.callbackData)) + return false; + +return true; +} diff --git a/libs/srvconf/netunit.h b/libs/srvconf/netunit.h new file mode 100644 index 00000000..34d730e1 --- /dev/null +++ b/libs/srvconf/netunit.h @@ -0,0 +1,75 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + */ + +#ifndef NetUnitH +#define NetUnitH + +#include + +#include + +namespace STG +{ + +class NETTRANSACT +{ +public: + typedef bool (* CALLBACK)(const std::string &, bool, void *); + + NETTRANSACT(const std::string & server, uint16_t port, + const std::string & login, const std::string & password); + NETTRANSACT(const std::string & server, uint16_t port, + const std::string & localAddress, uint16_t localPort, + const std::string & login, const std::string & password); + ~NETTRANSACT(); + int Transact(const std::string & request, CALLBACK f, void * data); + const std::string & GetError() const { return errorMsg; } + + int Connect(); + void Disconnect(); +private: + int TxHeader(); + int RxHeaderAnswer(); + + int TxLogin(); + int RxLoginAnswer(); + + int TxLoginS(); + int RxLoginSAnswer(); + + int TxData(const std::string & text); + int RxDataAnswer(CALLBACK f, void * data); + + std::string server; + uint16_t port; + std::string localAddress; + uint16_t localPort; + std::string login; + std::string password; + int sock; + std::string errorMsg; + + static bool TxCrypto(const void * block, size_t size, void * data); + static bool RxCrypto(const void * block, size_t size, void * data); +}; + +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/auth_by.cpp b/libs/srvconf/parsers/auth_by.cpp new file mode 100644 index 00000000..143eee26 --- /dev/null +++ b/libs/srvconf/parsers/auth_by.cpp @@ -0,0 +1,80 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "auth_by.h" + +#include // strcasecmp + +using namespace STG; + +AUTH_BY::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0), + parsingAnswer(false) +{ +} +//----------------------------------------------------------------------------- +int AUTH_BY::PARSER::ParseStart(const char *el, const char **attr) +{ +depth++; +if (depth == 1) + { + if (strcasecmp(el, "AuthorizedBy") == 0) + if (attr && attr[0] && attr[1]) + { + if (strcasecmp(attr[1], "error") == 0) + { + if (attr[2] && attr[3]) + error = attr[3]; + else + error = "User not found."; + } + else + parsingAnswer = true; + } + } +else + { + if (depth == 2) + { + if (parsingAnswer && strcasecmp(el, "Auth") == 0) + { + if (attr && attr[0] && attr[1] && strcasecmp(attr[0], "name") == 0) + info.push_back(attr[1]); + return 0; + } + } + } +return 0; +} +//----------------------------------------------------------------------------- +void AUTH_BY::PARSER::ParseEnd(const char * /*el*/) +{ +depth--; +if (depth == 0) + { + if (callback) + callback(error.empty(), error, info, data); + info.clear(); + error.clear(); + } +} diff --git a/libs/srvconf/parsers/auth_by.h b/libs/srvconf/parsers/auth_by.h new file mode 100644 index 00000000..5b2dfe52 --- /dev/null +++ b/libs/srvconf/parsers/auth_by.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_AUTH_BY_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_AUTH_BY_H__ + +#include "base.h" + +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace AUTH_BY +{ + +class PARSER: public STG::PARSER +{ +public: + PARSER(CALLBACK f, void * data, const std::string & encoding); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + CALLBACK callback; + void * data; + std::string encoding; + int depth; + bool parsingAnswer; + INFO info; + std::string error; +}; + +} // namespace AUTH_BY +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/base.h b/libs/srvconf/parsers/base.h new file mode 100644 index 00000000..4f84d874 --- /dev/null +++ b/libs/srvconf/parsers/base.h @@ -0,0 +1,41 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_H__ + +#include + +namespace STG +{ + +class PARSER +{ +public: + virtual ~PARSER() {} + virtual int ParseStart(const char * el, const char ** attr) = 0; + virtual void ParseEnd(const char * el) = 0; + virtual void Failure(const std::string & reason) = 0; +}; + +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/chg_admin.cpp b/libs/srvconf/parsers/chg_admin.cpp new file mode 100644 index 00000000..14679dff --- /dev/null +++ b/libs/srvconf/parsers/chg_admin.cpp @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "chg_admin.h" + +#include "stg/admin_conf.h" +#include "stg/common.h" + +#include + +using namespace STG; + +std::string CHG_ADMIN::Serialize(const ADMIN_CONF_RES & conf, const std::string & /*encoding*/) +{ +std::string params; +if (!conf.login.empty()) + params += " login=\"" + conf.login.data() + "\""; +if (!conf.password.empty()) + params += " password=\"" + conf.password.data() + "\""; +if (!conf.priv.empty()) + params += " priv=\"" + unsigned2str(conf.priv.data().ToInt()) + "\""; +return params; +} diff --git a/libs/srvconf/parsers/chg_admin.h b/libs/srvconf/parsers/chg_admin.h new file mode 100644 index 00000000..7041aa8e --- /dev/null +++ b/libs/srvconf/parsers/chg_admin.h @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_CHG_ADMIN_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_CHG_ADMIN_H__ + +#include "base.h" + +#include "stg/servconf_types.h" + +#include + +struct ADMIN_CONF_RES; + +namespace STG +{ +namespace CHG_ADMIN +{ + +std::string Serialize(const ADMIN_CONF_RES & conf, const std::string & encoding); + +} // namespace CHG_ADMIN +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/chg_corp.cpp b/libs/srvconf/parsers/chg_corp.cpp new file mode 100644 index 00000000..852fe8e1 --- /dev/null +++ b/libs/srvconf/parsers/chg_corp.cpp @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "chg_corp.h" + +#include "resetable_utils.h" + +#include "stg/corp_conf.h" +#include "stg/common.h" + +#include + +using namespace STG; + +std::string CHG_CORP::Serialize(const CORP_CONF_RES & conf, const std::string & /*encoding*/) +{ +std::ostringstream stream; + +appendResetableTag(stream, "name", conf.name); +appendResetableTag(stream, "cash", conf.cash); + +return stream.str(); +} diff --git a/libs/srvconf/parsers/chg_corp.h b/libs/srvconf/parsers/chg_corp.h new file mode 100644 index 00000000..b30482f7 --- /dev/null +++ b/libs/srvconf/parsers/chg_corp.h @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_CHG_CORP_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_CHG_CORP_H__ + +#include "base.h" + +#include "stg/servconf_types.h" + +#include + +struct CORP_CONF_RES; + +namespace STG +{ +namespace CHG_CORP +{ + +std::string Serialize(const CORP_CONF_RES & conf, const std::string & encoding); + +} // namespace CHG_CORP +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/chg_service.cpp b/libs/srvconf/parsers/chg_service.cpp new file mode 100644 index 00000000..6bea7565 --- /dev/null +++ b/libs/srvconf/parsers/chg_service.cpp @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "chg_service.h" + +#include "resetable_utils.h" + +#include "stg/service_conf.h" +#include "stg/common.h" + +#include + +using namespace STG; + +std::string CHG_SERVICE::Serialize(const SERVICE_CONF_RES & conf, const std::string & /*encoding*/) +{ +std::ostringstream stream; + +appendResetableAttr(stream, "name", conf.name); +appendResetableAttr(stream, "comment", MaybeEncode(conf.comment)); +appendResetableAttr(stream, "cost", conf.cost); +appendResetableAttr(stream, "payDay", conf.payDay); + +return stream.str(); +} diff --git a/libs/srvconf/parsers/chg_service.h b/libs/srvconf/parsers/chg_service.h new file mode 100644 index 00000000..09464a6e --- /dev/null +++ b/libs/srvconf/parsers/chg_service.h @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_CHG_SERVICE_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_CHG_SERVICE_H__ + +#include "base.h" + +#include "stg/servconf_types.h" + +#include + +struct SERVICE_CONF_RES; + +namespace STG +{ +namespace CHG_SERVICE +{ + +std::string Serialize(const SERVICE_CONF_RES & conf, const std::string & encoding); + +} // namespace CHG_SERVICE +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/chg_tariff.cpp b/libs/srvconf/parsers/chg_tariff.cpp new file mode 100644 index 00000000..16c4b198 --- /dev/null +++ b/libs/srvconf/parsers/chg_tariff.cpp @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "chg_tariff.h" + +#include "resetable_utils.h" + +#include "stg/tariff_conf.h" +#include "stg/common.h" + +#include + +#include + +using namespace STG; + +namespace +{ + +template +void appendSlashedResetable(std::ostream & stream, const std::string & name, const A & array, T A::value_type:: * field) +{ +std::string res; +for (typename A::size_type i = 0; i < array.size(); ++i) + { + if ((array[i].*field).empty()) // All values must be set + return; + if (!res.empty()) + res += "/"; + res += x2str((array[i].*field).data()); + } +stream << "<" << name << " value=\"" << res << "\"/>"; +} + +} // namespace anonymous + +std::string CHG_TARIFF::Serialize(const TARIFF_DATA_RES & data, const std::string & /*encoding*/) +{ +std::ostringstream stream; + +appendResetableTag(stream, "fee", data.tariffConf.fee); +appendResetableTag(stream, "passiveCost", data.tariffConf.passiveCost); +appendResetableTag(stream, "free", data.tariffConf.free); + +if (!data.tariffConf.traffType.empty()) + stream << ""; + +if (!data.tariffConf.period.empty()) + switch (data.tariffConf.period.data()) + { + case TARIFF::DAY: stream << ""; break; + case TARIFF::MONTH: stream << ""; break; + } + +if (!data.tariffConf.changePolicy.empty()) + switch (data.tariffConf.changePolicy.data()) + { + case TARIFF::ALLOW: stream << ""; break; + case TARIFF::TO_CHEAP: stream << ""; break; + case TARIFF::TO_EXPENSIVE: stream << ""; break; + case TARIFF::DENY: stream << ""; break; + } + +appendResetableTag(stream, "changePolicyTimeout", data.tariffConf.changePolicyTimeout); +for (size_t i = 0; i < DIR_NUM; ++i) + if (!data.dirPrice[i].hDay.empty() && + !data.dirPrice[i].mDay.empty() && + !data.dirPrice[i].hNight.empty() && + !data.dirPrice[i].mNight.empty()) + stream << ""; + +appendSlashedResetable(stream, "priceDayA", data.dirPrice, &DIRPRICE_DATA_RES::priceDayA); +appendSlashedResetable(stream, "priceDayB", data.dirPrice, &DIRPRICE_DATA_RES::priceDayB); +appendSlashedResetable(stream, "priceNightA", data.dirPrice, &DIRPRICE_DATA_RES::priceNightA); +appendSlashedResetable(stream, "priceNightB", data.dirPrice, &DIRPRICE_DATA_RES::priceNightB); +appendSlashedResetable(stream, "singlePrice", data.dirPrice, &DIRPRICE_DATA_RES::singlePrice); +appendSlashedResetable(stream, "noDiscount", data.dirPrice, &DIRPRICE_DATA_RES::noDiscount); +appendSlashedResetable(stream, "threshold", data.dirPrice, &DIRPRICE_DATA_RES::threshold); + +return stream.str(); +} diff --git a/libs/srvconf/parsers/chg_tariff.h b/libs/srvconf/parsers/chg_tariff.h new file mode 100644 index 00000000..142b0155 --- /dev/null +++ b/libs/srvconf/parsers/chg_tariff.h @@ -0,0 +1,42 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_CHG_TARIFF_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_CHG_TARIFF_H__ + +#include "base.h" + +#include "stg/servconf_types.h" + +#include + +struct TARIFF_DATA_RES; + +namespace STG +{ +namespace CHG_TARIFF +{ + +std::string Serialize(const TARIFF_DATA_RES & data, const std::string & encoding); + +} // namespace CHG_TARIFF +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/chg_user.cpp b/libs/srvconf/parsers/chg_user.cpp new file mode 100644 index 00000000..e30392f3 --- /dev/null +++ b/libs/srvconf/parsers/chg_user.cpp @@ -0,0 +1,143 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#include "chg_user.h" + +#include "resetable_utils.h" + +#include "stg/user_conf.h" +#include "stg/user_stat.h" +#include "stg/common.h" + +#include +#include + +#include + +using namespace STG; + +CHG_USER::PARSER::PARSER(SIMPLE::CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0) +{ +} +//----------------------------------------------------------------------------- +int CHG_USER::PARSER::ParseStart(const char *el, const char **attr) +{ +depth++; +if (depth == 1) + { + if (strcasecmp(el, "SetUser") == 0) + ParseAnswer(el, attr); + else if (strcasecmp(el, "DelUser") == 0) + ParseAnswer(el, attr); + else if (strcasecmp(el, "AddUser") == 0) + ParseAnswer(el, attr); + } +return 0; +} +//----------------------------------------------------------------------------- +void CHG_USER::PARSER::ParseEnd(const char *) +{ +depth--; +} +//----------------------------------------------------------------------------- +void CHG_USER::PARSER::ParseAnswer(const char * /*el*/, const char ** attr) +{ +if (!callback) + return; +if (attr && attr[0] && attr[1]) + callback(strcasecmp(attr[1], "ok") == 0, attr[2] && attr[3] ? attr[3] : "", data); +else + callback(false, "Invalid response.", data); +} + +std::string CHG_USER::Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat, const std::string & encoding) +{ +std::ostringstream stream; + +// Conf + +appendResetableTag(stream, "credit", conf.credit); +appendResetableTag(stream, "creditExpire", conf.creditExpire); +appendResetableTag(stream, "password", conf.password); +appendResetableTag(stream, "down", conf.disabled); // TODO: down -> disabled +appendResetableTag(stream, "passive", conf.passive); +appendResetableTag(stream, "disableDetailStat", conf.disabledDetailStat); // TODO: disable -> disabled +appendResetableTag(stream, "aonline", conf.alwaysOnline); // TODO: aonline -> alwaysOnline +appendResetableTag(stream, "ip", conf.ips); // TODO: ip -> ips + +if (!conf.nextTariff.empty()) + stream << ""; +else if (!conf.tariffName.empty()) + stream << ""; + +appendResetableTag(stream, "note", MaybeEncode(MaybeIconv(conf.note, encoding, "koi8-ru"))); +appendResetableTag(stream, "name", MaybeEncode(MaybeIconv(conf.realName, encoding, "koi8-ru"))); // TODO: name -> realName +appendResetableTag(stream, "address", MaybeEncode(MaybeIconv(conf.address, encoding, "koi8-ru"))); +appendResetableTag(stream, "email", MaybeEncode(MaybeIconv(conf.email, encoding, "koi8-ru"))); +appendResetableTag(stream, "phone", MaybeEncode(MaybeIconv(conf.phone, encoding, "cp1251"))); +appendResetableTag(stream, "group", MaybeEncode(MaybeIconv(conf.group, encoding, "koi8-ru"))); +appendResetableTag(stream, "corp", conf.corp); + +for (size_t i = 0; i < conf.userdata.size(); ++i) + appendResetableTag(stream, "userdata", i, MaybeEncode(MaybeIconv(conf.userdata[i], encoding, "koi8-ru"))); + +if (!conf.services.empty()) + { + stream << ""; + for (size_t i = 0; i < conf.services.data().size(); ++i) + stream << ""; + stream << ""; + } + +// Stat + +if (!stat.cashAdd.empty()) + stream << ""; +else if (!stat.cashSet.empty()) + stream << ""; + +appendResetableTag(stream, "freeMb", stat.freeMb); + +std::ostringstream traff; +for (size_t i = 0; i < stat.sessionUp.size(); ++i) + if (!stat.sessionUp[i].empty()) + traff << " SU" << i << "=\"" << stat.sessionUp[i].data() << "\""; +for (size_t i = 0; i < stat.sessionDown.size(); ++i) + if (!stat.sessionDown[i].empty()) + traff << " SD" << i << "=\"" << stat.sessionDown[i].data() << "\""; +for (size_t i = 0; i < stat.monthUp.size(); ++i) + if (!stat.monthUp[i].empty()) + traff << " MU" << i << "=\"" << stat.monthUp[i].data() << "\""; +for (size_t i = 0; i < stat.monthDown.size(); ++i) + if (!stat.monthDown[i].empty()) + traff << " MD" << i << "=\"" << stat.monthDown[i].data() << "\""; + +std::string traffData = traff.str(); +if (!traffData.empty()) + stream << ""; + +std::cerr << stream.str() << "\n"; +return stream.str(); +} diff --git a/libs/srvconf/parsers/chg_user.h b/libs/srvconf/parsers/chg_user.h new file mode 100644 index 00000000..9ac559e0 --- /dev/null +++ b/libs/srvconf/parsers/chg_user.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_CHG_USER_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_CHG_USER_H__ + +#include "base.h" + +#include "stg/servconf_types.h" + +struct USER_CONF_RES; +struct USER_STAT_RES; + +namespace STG +{ +namespace CHG_USER +{ + +class PARSER: public STG::PARSER +{ +public: + PARSER(SIMPLE::CALLBACK f, void * data, const std::string & encoding); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, data); } + +private: + SIMPLE::CALLBACK callback; + void * data; + std::string encoding; + int depth; + + void ParseAnswer(const char * el, const char ** attr); +}; + +std::string Serialize(const USER_CONF_RES & conf, const USER_STAT_RES & stat, const std::string & encoding); + +} // namespace CHG_USER +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/get_admin.cpp b/libs/srvconf/parsers/get_admin.cpp new file mode 100644 index 00000000..9f4ec5d4 --- /dev/null +++ b/libs/srvconf/parsers/get_admin.cpp @@ -0,0 +1,124 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "get_admin.h" + +#include "stg/common.h" + +#include +#include + +#include + +using namespace STG; + +namespace STG +{ + +template <> +inline +bool GetValue(const char ** attr, PRIV & value, const std::string & attrName) +{ +uint32_t priv; +if (!GetValue(attr, priv, attrName)) + return false; +value = PRIV(priv); +return true; +} + +} // namespace STG + +GET_ADMIN::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0), + parsingAnswer(false) +{ + AddParser(propertyParsers, "login", info.login); + AddParser(propertyParsers, "password", info.password); + AddParser(propertyParsers, "priv", info.priv); +} +//----------------------------------------------------------------------------- +GET_ADMIN::PARSER::~PARSER() +{ + PROPERTY_PARSERS::iterator it(propertyParsers.begin()); + while (it != propertyParsers.end()) + delete (it++)->second; +} +//----------------------------------------------------------------------------- +int GET_ADMIN::PARSER::ParseStart(const char * el, const char ** attr) +{ +depth++; +if (depth == 1) + ParseAdmin(el, attr); + +/*if (depth == 2 && parsingAnswer) + ParseAdminParams(el, attr);*/ + +return 0; +} +//----------------------------------------------------------------------------- +void GET_ADMIN::PARSER::ParseEnd(const char * /*el*/) +{ +depth--; +if (depth == 0 && parsingAnswer) + { + if (callback) + callback(error.empty(), error, info, data); + error.clear(); + parsingAnswer = false; + } +} +//----------------------------------------------------------------------------- +void GET_ADMIN::PARSER::ParseAdmin(const char * el, const char ** attr) +{ +if (strcasecmp(el, "admin") == 0) + { + if (attr && attr[0] && attr[1]) + { + if (strcasecmp(attr[1], "error") == 0) + { + if (attr[2] && attr[3]) + error = attr[3]; + else + error = "Admin not found."; + } + else + { + parsingAnswer = true; + for (const char ** pos = attr; *pos != NULL; pos = pos + 2) + if (!TryParse(propertyParsers, ToLower(*pos), pos, encoding, *pos)) + { + error = std::string("Invalid parameter '") + *pos + "'."; + break; + } + } + } + else + parsingAnswer = true; + } +} +//----------------------------------------------------------------------------- +/*void GET_ADMIN::PARSER::ParseAdminParams(const char * el, const char ** attr) +{ +if (!TryParse(propertyParsers, ToLower(el), attr)) + error = "Invalid parameter."; +}*/ diff --git a/libs/srvconf/parsers/get_admin.h b/libs/srvconf/parsers/get_admin.h new file mode 100644 index 00000000..f7cb3084 --- /dev/null +++ b/libs/srvconf/parsers/get_admin.h @@ -0,0 +1,65 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_ADMIN_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_GET_ADMIN_H__ + +#include "base.h" +#include "property.h" + +#include "stg/admin_conf.h" +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace GET_ADMIN +{ + +class PARSER: public STG::PARSER +{ +public: + typedef GET_ADMIN::INFO INFO; + + PARSER(CALLBACK f, void * data, const std::string & encoding); + virtual ~PARSER(); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + PROPERTY_PARSERS propertyParsers; + CALLBACK callback; + void * data; + std::string encoding; + INFO info; + int depth; + bool parsingAnswer; + std::string error; + + void ParseAdmin(const char * el, const char ** attr); + //void ParseAdminParams(const char * el, const char ** attr); +}; + +} // namespace GET_ADMIN +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/get_container.h b/libs/srvconf/parsers/get_container.h new file mode 100644 index 00000000..cbfd1ead --- /dev/null +++ b/libs/srvconf/parsers/get_container.h @@ -0,0 +1,104 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_CONTAINER_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_GET_CONTAINER_H__ + +#include "base.h" + +#include + +#include + +namespace STG +{ +namespace GET_CONTAINER +{ + +template +class PARSER: public STG::PARSER +{ +public: + typedef std::vector INFO; + typedef void (* CALLBACK)(bool result, const std::string & reason, const INFO & info, void * data); + PARSER(const std::string & t, CALLBACK f, void * d, const std::string & e) + : tag(t), callback(f), data(d), encoding(e), + elementParser(&PARSER::ElementCallback, this, e), + depth(0), parsingAnswer(false) + {} + int ParseStart(const char * el, const char ** attr) + { + depth++; + if (depth == 1 && strcasecmp(el, tag.c_str()) == 0) + parsingAnswer = true; + + if (depth > 1 && parsingAnswer) + elementParser.ParseStart(el, attr); + + return 0; + } + void ParseEnd(const char * el) + { + depth--; + if (depth > 0 && parsingAnswer) + elementParser.ParseEnd(el); + + if (depth == 0 && parsingAnswer) + { + if (callback) + callback(error.empty(), error, info, data); + error.clear(); + info.clear(); + parsingAnswer = false; + } + } + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + std::string tag; + CALLBACK callback; + void * data; + std::string encoding; + ELEMENT_PARSER elementParser; + INFO info; + int depth; + bool parsingAnswer; + std::string error; + + void AddElement(const typename ELEMENT_PARSER::INFO & elementInfo) + { + info.push_back(elementInfo); + } + void SetError(const std::string & e) { error = e; } + + static void ElementCallback(bool result, const std::string& reason, const typename ELEMENT_PARSER::INFO & info, void * data) + { + PARSER * parser = static_cast *>(data); + if (!result) + parser->SetError(reason); + else + parser->AddElement(info); + } +}; + +} // namespace GET_CONTAINER +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/get_corp.cpp b/libs/srvconf/parsers/get_corp.cpp new file mode 100644 index 00000000..0a6a1e02 --- /dev/null +++ b/libs/srvconf/parsers/get_corp.cpp @@ -0,0 +1,98 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "get_corp.h" + +//#include "parsers/property.h" + +#include "stg/common.h" + +#include + +using namespace STG; + +GET_CORP::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0), + parsingAnswer(false) +{ + AddParser(propertyParsers, "name", info.name); + AddParser(propertyParsers, "cash", info.cash); +} +//----------------------------------------------------------------------------- +GET_CORP::PARSER::~PARSER() +{ + PROPERTY_PARSERS::iterator it(propertyParsers.begin()); + while (it != propertyParsers.end()) + delete (it++)->second; +} +//----------------------------------------------------------------------------- +int GET_CORP::PARSER::ParseStart(const char * el, const char ** attr) +{ +depth++; +if (depth == 1) + ParseCorp(el, attr); + +if (depth == 2 && parsingAnswer) + ParseCorpParams(el, attr); + +return 0; +} +//----------------------------------------------------------------------------- +void GET_CORP::PARSER::ParseEnd(const char * /*el*/) +{ +depth--; +if (depth == 0 && parsingAnswer) + { + if (callback) + callback(error.empty(), error, info, data); + error.clear(); + parsingAnswer = false; + } +} +//----------------------------------------------------------------------------- +void GET_CORP::PARSER::ParseCorp(const char * el, const char ** attr) +{ +if (strcasecmp(el, "corp") == 0) + { + if (attr && attr[0] && attr[1]) + { + if (strcasecmp(attr[1], "error") == 0) + { + if (attr[2] && attr[3]) + error = attr[3]; + else + error = "Corp not found."; + } + else + parsingAnswer = true; + } + else + parsingAnswer = true; + } +} +//----------------------------------------------------------------------------- +void GET_CORP::PARSER::ParseCorpParams(const char * el, const char ** attr) +{ +if (!TryParse(propertyParsers, ToLower(el), attr, encoding)) + error = "Invalid parameter."; +} diff --git a/libs/srvconf/parsers/get_corp.h b/libs/srvconf/parsers/get_corp.h new file mode 100644 index 00000000..b9d87983 --- /dev/null +++ b/libs/srvconf/parsers/get_corp.h @@ -0,0 +1,65 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_CORP_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_GET_CORP_H__ + +#include "base.h" +#include "property.h" + +#include "stg/corp_conf.h" +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace GET_CORP +{ + +class PARSER: public STG::PARSER +{ +public: + typedef GET_CORP::INFO INFO; + + PARSER(CALLBACK f, void * data, const std::string & encoding); + virtual ~PARSER(); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + PROPERTY_PARSERS propertyParsers; + CALLBACK callback; + void * data; + INFO info; + std::string encoding; + int depth; + bool parsingAnswer; + std::string error; + + void ParseCorp(const char * el, const char ** attr); + void ParseCorpParams(const char * el, const char ** attr); +}; + +} // namespace GET_CORP +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/get_service.cpp b/libs/srvconf/parsers/get_service.cpp new file mode 100644 index 00000000..fd19a2ff --- /dev/null +++ b/libs/srvconf/parsers/get_service.cpp @@ -0,0 +1,108 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "get_service.h" + +//#include "parsers/property.h" + +#include "stg/common.h" + +#include + +using namespace STG; + +GET_SERVICE::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0), + parsingAnswer(false) +{ + AddParser(propertyParsers, "name", info.name); + AddParser(propertyParsers, "comment", info.comment, GetEncodedValue); + AddParser(propertyParsers, "cost", info.cost); + AddParser(propertyParsers, "payDay", info.payDay); +} +//----------------------------------------------------------------------------- +GET_SERVICE::PARSER::~PARSER() +{ + PROPERTY_PARSERS::iterator it(propertyParsers.begin()); + while (it != propertyParsers.end()) + delete (it++)->second; +} +//----------------------------------------------------------------------------- +int GET_SERVICE::PARSER::ParseStart(const char * el, const char ** attr) +{ +depth++; +if (depth == 1) + ParseService(el, attr); + +/*if (depth == 2 && parsingAnswer) + ParseServiceParams(el, attr);*/ + +return 0; +} +//----------------------------------------------------------------------------- +void GET_SERVICE::PARSER::ParseEnd(const char * /*el*/) +{ +depth--; +if (depth == 0 && parsingAnswer) + { + if (callback) + callback(error.empty(), error, info, data); + error.clear(); + parsingAnswer = false; + } +} +//----------------------------------------------------------------------------- +void GET_SERVICE::PARSER::ParseService(const char * el, const char ** attr) +{ +if (strcasecmp(el, "service") == 0) + { + if (attr && attr[0] && attr[1]) + { + if (strcasecmp(attr[1], "error") == 0) + { + if (attr[2] && attr[3]) + error = attr[3]; + else + error = "Service not found."; + } + else + { + parsingAnswer = true; + for (const char ** pos = attr; *pos != NULL; pos = pos + 2) + if (!TryParse(propertyParsers, ToLower(*pos), pos, encoding, *pos)) + { + error = std::string("Invalid parameter '") + *pos + "' or value '" + *(pos + 1) + "'."; + break; + } + } + } + else + parsingAnswer = true; + } +} +//----------------------------------------------------------------------------- +/*void GET_SERVICE::PARSER::ParseServiceParams(const char * el, const char ** attr) +{ +if (!TryParse(propertyParsers, ToLower(el), attr, encoding)) + error = "Invalid parameter."; +}*/ diff --git a/libs/srvconf/parsers/get_service.h b/libs/srvconf/parsers/get_service.h new file mode 100644 index 00000000..d8213627 --- /dev/null +++ b/libs/srvconf/parsers/get_service.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_SERVICE_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_GET_SERVICE_H__ + +#include "base.h" +#include "property.h" + +#include "stg/service_conf.h" +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace GET_SERVICE +{ + +class PARSER: public STG::PARSER +{ +public: + typedef GET_SERVICE::INFO INFO; + PARSER(CALLBACK f, void * data, const std::string & encoding); + virtual ~PARSER(); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + PROPERTY_PARSERS propertyParsers; + CALLBACK callback; + void * data; + INFO info; + std::string encoding; + int depth; + bool parsingAnswer; + std::string error; + + void ParseService(const char * el, const char ** attr); + //void ParseServiceParams(const char * el, const char ** attr); +}; + +} // namespace GET_SERVICE +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/get_tariff.cpp b/libs/srvconf/parsers/get_tariff.cpp new file mode 100644 index 00000000..7a6f9053 --- /dev/null +++ b/libs/srvconf/parsers/get_tariff.cpp @@ -0,0 +1,226 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "get_tariff.h" + +//#include "parsers/property.h" + +#include "stg/common.h" + +#include + +#include + +using namespace STG; + +namespace +{ + +template +class AOS_PARSER : public BASE_PROPERTY_PARSER +{ + public: + typedef bool (* FUNC)(const char **, A &, T A::value_type:: *); + AOS_PARSER(A & a, T A::value_type:: * fld, FUNC f) : array(a), field(fld), func(f) {} + virtual bool Parse(const char ** attr, const std::string & /*attrName*/, const std::string & /*fromEncoding*/) { return func(attr, array, field); } + private: + A & array; + T A::value_type:: * field; + FUNC func; +}; + +template +inline +void AddAOSParser(PROPERTY_PARSERS & parsers, const std::string & name, A & array, T A::value_type:: * field, const typename AOS_PARSER::FUNC & func) +{ + parsers.insert(std::make_pair(ToLower(name), new AOS_PARSER(array, field, func))); +} + +bool GetTimeSpan(const char ** attr, DIRPRICE_DATA & value, const std::string & attrName) +{ +if (CheckValue(attr, attrName)) + { + int hb = 0; + int mb = 0; + int he = 0; + int me = 0; + if (ParseTariffTimeStr(attr[1], hb, mb, he, me) == 0) + { + value.hDay = hb; + value.mDay = mb; + value.hNight = he; + value.mNight = me; + return true; + } + } +return false; +} + +template +bool GetTraffType(const char ** attr, T & value, const std::string & attrName) +{ +if (!CheckValue(attr, attrName)) + return false; +value = TARIFF::StringToTraffType(attr[1]); +return true; +} + +template +bool GetPeriod(const char ** attr, T & value, const std::string & attrName) +{ +if (!CheckValue(attr, attrName)) + return false; +std::string type(attr[1]); +if (type == "day") + value = TARIFF::DAY; +else if (type == "month") + value = TARIFF::MONTH; +else + return false; +return true; +} + +template +bool GetChangePolicy(const char ** attr, T & value, const std::string & attrName) +{ +if (!CheckValue(attr, attrName)) + return false; +std::string type(attr[1]); +if (type == "allow") + value = TARIFF::ALLOW; +else if (type == "to_cheap") + value = TARIFF::TO_CHEAP; +else if (type == "to_expensive") + value = TARIFF::TO_EXPENSIVE; +else if (type == "deny") + value = TARIFF::DENY; +else + return false; +return true; +} + +template +bool GetSlashedValue(const char ** attr, A & array, T A::value_type:: * field) +{ +if (!CheckValue(attr, "value")) + return false; +const char * start = attr[1]; +size_t item = 0; +const char * pos = NULL; +while ((pos = strchr(start, '/')) && item < array.size()) + { + if (str2x(std::string(start, pos), array[item++].*field)) + return false; + start = pos + 1; + } +if (item < array.size()) + if (str2x(start, array[item].*field)) + return false; +return true; +} + +} // namespace anonymous + +GET_TARIFF::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0), + parsingAnswer(false) +{ + AddParser(propertyParsers, "fee", info.tariffConf.fee); + AddParser(propertyParsers, "passiveCost", info.tariffConf.passiveCost); + AddParser(propertyParsers, "free", info.tariffConf.free); + AddParser(propertyParsers, "traffType", info.tariffConf.traffType, GetTraffType); + AddParser(propertyParsers, "period", info.tariffConf.period, GetPeriod); + AddParser(propertyParsers, "changePolicy", info.tariffConf.changePolicy, GetChangePolicy); + AddParser(propertyParsers, "changePolicyTimeout", info.tariffConf.changePolicyTimeout); + for (size_t i = 0; i < DIR_NUM; ++i) + AddParser(propertyParsers, "time" + unsigned2str(i), info.dirPrice[i], GetTimeSpan); + AddAOSParser(propertyParsers, "priceDayA", info.dirPrice, &DIRPRICE_DATA::priceDayA, GetSlashedValue); + AddAOSParser(propertyParsers, "priceDayB", info.dirPrice, &DIRPRICE_DATA::priceDayB, GetSlashedValue); + AddAOSParser(propertyParsers, "priceNightA", info.dirPrice, &DIRPRICE_DATA::priceNightA, GetSlashedValue); + AddAOSParser(propertyParsers, "priceNightB", info.dirPrice, &DIRPRICE_DATA::priceNightB, GetSlashedValue); + AddAOSParser(propertyParsers, "singlePrice", info.dirPrice, &DIRPRICE_DATA::singlePrice, GetSlashedValue); + AddAOSParser(propertyParsers, "noDiscount", info.dirPrice, &DIRPRICE_DATA::noDiscount, GetSlashedValue); + AddAOSParser(propertyParsers, "threshold", info.dirPrice, &DIRPRICE_DATA::threshold, GetSlashedValue); +} +//----------------------------------------------------------------------------- +GET_TARIFF::PARSER::~PARSER() +{ + PROPERTY_PARSERS::iterator it(propertyParsers.begin()); + while (it != propertyParsers.end()) + delete (it++)->second; +} +//----------------------------------------------------------------------------- +int GET_TARIFF::PARSER::ParseStart(const char * el, const char ** attr) +{ +depth++; +if (depth == 1) + ParseTariff(el, attr); + +if (depth == 2 && parsingAnswer) + ParseTariffParams(el, attr); + +return 0; +} +//----------------------------------------------------------------------------- +void GET_TARIFF::PARSER::ParseEnd(const char * /*el*/) +{ +depth--; +if (depth == 0 && parsingAnswer) + { + if (callback) + callback(error.empty(), error, info, data); + error.clear(); + parsingAnswer = false; + } +} +//----------------------------------------------------------------------------- +void GET_TARIFF::PARSER::ParseTariff(const char * el, const char ** attr) +{ +if (strcasecmp(el, "tariff") == 0) + { + if (attr && attr[0] && attr[1]) + { + if (strcasecmp(attr[1], "error") == 0) + { + if (attr[2] && attr[3]) + error = attr[3]; + else + error = "Tariff not found."; + } + else + { + parsingAnswer = true; + if (strcasecmp(attr[0], "name") == 0) + info.tariffConf.name = attr[1]; + } + } + else + parsingAnswer = true; + } +} +//----------------------------------------------------------------------------- +void GET_TARIFF::PARSER::ParseTariffParams(const char * el, const char ** attr) +{ +if (!TryParse(propertyParsers, ToLower(el), attr, encoding)) + error = std::string("Invalid parameter '") + el + "'."; +} diff --git a/libs/srvconf/parsers/get_tariff.h b/libs/srvconf/parsers/get_tariff.h new file mode 100644 index 00000000..be78fdbd --- /dev/null +++ b/libs/srvconf/parsers/get_tariff.h @@ -0,0 +1,65 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_TARIFF_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_GET_TARIFF_H__ + +#include "base.h" +#include "property.h" + +#include "stg/tariff_conf.h" +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace GET_TARIFF +{ + +class PARSER: public STG::PARSER +{ +public: + typedef GET_TARIFF::INFO INFO; + + PARSER(CALLBACK f, void * data, const std::string & encoding); + virtual ~PARSER(); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + PROPERTY_PARSERS propertyParsers; + CALLBACK callback; + void * data; + std::string encoding; + INFO info; + int depth; + bool parsingAnswer; + std::string error; + + void ParseTariff(const char * el, const char ** attr); + void ParseTariffParams(const char * el, const char ** attr); +}; + +} // namespace GET_TARIFF +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/get_user.cpp b/libs/srvconf/parsers/get_user.cpp new file mode 100644 index 00000000..03327c4d --- /dev/null +++ b/libs/srvconf/parsers/get_user.cpp @@ -0,0 +1,182 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#include "get_user.h" + +#include "stg/common.h" + +#include +#include + +#include + +using namespace STG; + +namespace STG +{ + +template <> +bool GetValue(const char ** attr, GET_USER::STAT & value, const std::string & /*attrName*/) +{ +if (!attr) + return false; +std::map props; +for (size_t i = 0; i < DIR_NUM; ++i) + { + props.insert(std::pair("su" + unsigned2str(i), &value.su[i])); + props.insert(std::pair("sd" + unsigned2str(i), &value.sd[i])); + props.insert(std::pair("mu" + unsigned2str(i), &value.mu[i])); + props.insert(std::pair("md" + unsigned2str(i), &value.md[i])); + } +size_t pos = 0; +while (attr[pos]) + { + std::string name(ToLower(attr[pos++])); + std::map::iterator it(props.find(name)); + if (it != props.end()) + if (str2x(attr[pos++], *it->second) < 0) + return false; + } +return true; +} + +} + +GET_USER::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0), + parsingAnswer(false) +{ + AddParser(propertyParsers, "login", info.login); + AddParser(propertyParsers, "password", info.password); + AddParser(propertyParsers, "cash", info.cash); + AddParser(propertyParsers, "credit", info.credit); + AddParser(propertyParsers, "creditExpire", info.creditExpire); + AddParser(propertyParsers, "lastCash", info.lastCashAdd); + AddParser(propertyParsers, "lastTimeCash", info.lastCashAddTime); + AddParser(propertyParsers, "freeMb", info.prepaidTraff); + AddParser(propertyParsers, "down", info.disabled); + AddParser(propertyParsers, "passive", info.passive); + AddParser(propertyParsers, "disableDetailStat", info.disableDetailStat); + AddParser(propertyParsers, "status", info.connected); + AddParser(propertyParsers, "aonline", info.alwaysOnline); + AddParser(propertyParsers, "currIP", info.ip, GetIPValue); + AddParser(propertyParsers, "ip", info.ips); + AddParser(propertyParsers, "tariff", info.tariff); + AddParser(propertyParsers, "group", info.group, "koi8-ru", GetEncodedValue); + AddParser(propertyParsers, "note", info.note, "koi8-ru", GetEncodedValue); + AddParser(propertyParsers, "email", info.email, "koi8-ru", GetEncodedValue); + AddParser(propertyParsers, "name", info.name, "koi8-ru", GetEncodedValue); + AddParser(propertyParsers, "address", info.address, "koi8-ru", GetEncodedValue); + AddParser(propertyParsers, "phone", info.phone, "cp1251", GetEncodedValue); + AddParser(propertyParsers, "corp", info.corp); + AddParser(propertyParsers, "traff", info.stat); + AddParser(propertyParsers, "pingTime", info.pingTime); + AddParser(propertyParsers, "lastActivityTime", info.lastActivityTime); + + for (size_t i = 0; i < USERDATA_NUM; ++i) + AddParser(propertyParsers, "userData" + unsigned2str(i), info.userData[i], "koi8-ru", GetEncodedValue); +} +//----------------------------------------------------------------------------- +GET_USER::PARSER::~PARSER() +{ + PROPERTY_PARSERS::iterator it(propertyParsers.begin()); + while (it != propertyParsers.end()) + delete (it++)->second; +} +//----------------------------------------------------------------------------- +int GET_USER::PARSER::ParseStart(const char * el, const char ** attr) +{ +depth++; +if (depth == 1) + ParseUser(el, attr); + +if (depth == 2 && parsingAnswer) + ParseUserParams(el, attr); + +if (depth == 3 && parsingAnswer) + { + ParseAuthBy(el, attr); + ParseServices(el, attr); + } + +return 0; +} +//----------------------------------------------------------------------------- +void GET_USER::PARSER::ParseEnd(const char * /*el*/) +{ +depth--; +if (depth == 0 && parsingAnswer) + { + if (callback) + callback(error.empty(), error, info, data); + error.clear(); + parsingAnswer = false; + } +} +//----------------------------------------------------------------------------- +void GET_USER::PARSER::ParseUser(const char * el, const char ** attr) +{ +if (strcasecmp(el, "user") == 0) + { + if (attr && attr[0] && attr[1]) + { + if (strcasecmp(attr[1], "error") == 0) + { + if (attr[2] && attr[3]) + error = attr[3]; + else + error = "User not found."; + } + else if (strcasecmp(attr[0], "login") == 0 && attr[1]) + info.login = attr[1]; + } + parsingAnswer = true; + } +} +//----------------------------------------------------------------------------- +void GET_USER::PARSER::ParseUserParams(const char * el, const char ** attr) +{ +if (strcasecmp(el, "AuthorizedBy") != 0 && + !TryParse(propertyParsers, ToLower(el), attr, encoding)) + error = "Invalid parameter."; +else if (strcasecmp(el, "Services") != 0 && + !TryParse(propertyParsers, ToLower(el), attr, encoding)) + error = "Invalid parameter."; +} +//----------------------------------------------------------------------------- +void GET_USER::PARSER::ParseAuthBy(const char * el, const char ** attr) +{ +if (strcasecmp(el, "Auth") == 0 && + attr && attr[0] && attr[1] && + strcasecmp(attr[0], "name") == 0) + info.authBy.push_back(attr[1]); +} +//----------------------------------------------------------------------------- +void GET_USER::PARSER::ParseServices(const char * el, const char ** attr) +{ +if (strcasecmp(el, "Service") == 0 && + attr && attr[0] && attr[1] && + strcasecmp(attr[0], "name") == 0) + info.services.push_back(attr[1]); +} diff --git a/libs/srvconf/parsers/get_user.h b/libs/srvconf/parsers/get_user.h new file mode 100644 index 00000000..a0e3e3a4 --- /dev/null +++ b/libs/srvconf/parsers/get_user.h @@ -0,0 +1,67 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_GET_USER_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_GET_USER_H__ + +#include "base.h" +#include "property.h" + +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace GET_USER +{ + +class PARSER: public STG::PARSER +{ +public: + typedef GET_USER::INFO INFO; + + PARSER(CALLBACK f, void * data, const std::string & encoding); + virtual ~PARSER(); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + PROPERTY_PARSERS propertyParsers; + CALLBACK callback; + void * data; + std::string encoding; + INFO info; + int depth; + bool parsingAnswer; + std::string error; + + void ParseUser(const char * el, const char ** attr); + void ParseUserParams(const char * el, const char ** attr); + void ParseAuthBy(const char * el, const char ** attr); + void ParseServices(const char * el, const char ** attr); +}; + +} // namespace GET_USER +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/property.cpp b/libs/srvconf/parsers/property.cpp new file mode 100644 index 00000000..eb9c2dfb --- /dev/null +++ b/libs/srvconf/parsers/property.cpp @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "property.h" + +#include + +bool STG::CheckValue(const char ** attr, const std::string & attrName) +{ +return attr && attr[0] && attr[1] && strcasecmp(attr[0], attrName.c_str()) == 0; +} + +bool STG::GetEncodedValue(const char ** attr, std::string & value, const std::string & attrName) +{ +if (!CheckValue(attr, attrName)) + return false; +Decode21str(value, attr[1]); +return true; +} + +bool STG::GetIPValue(const char ** attr, uint32_t & value, const std::string & attrName) +{ +if (!CheckValue(attr, attrName)) + return false; +std::string ip(attr[1]); +value = inet_strington(attr[1]); +if (value == 0 && ip != "0.0.0.0") + return false; +return true; +} + +bool STG::TryParse(PROPERTY_PARSERS & parsers, const std::string & name, const char ** attr, const std::string & toEncoding, const std::string & attrName) +{ + PROPERTY_PARSERS::iterator it(parsers.find(name)); + if (it != parsers.end()) + return it->second->Parse(attr, attrName, toEncoding); + return true; // Assume that non-existing params are ok. +} diff --git a/libs/srvconf/parsers/property.h b/libs/srvconf/parsers/property.h new file mode 100644 index 00000000..7aa98aeb --- /dev/null +++ b/libs/srvconf/parsers/property.h @@ -0,0 +1,125 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PROPERTY_PARSERS_H__ +#define __STG_STGLIBS_SRVCONF_PROPERTY_PARSERS_H__ + +#include "stg/common.h" + +#include +#include + +namespace STG +{ + +class BASE_PROPERTY_PARSER +{ + public: + virtual ~BASE_PROPERTY_PARSER() {} + virtual bool Parse(const char ** attr, const std::string & attrName, const std::string & fromEncoding) = 0; +}; + +template +class PROPERTY_PARSER : public BASE_PROPERTY_PARSER +{ + public: + typedef bool (* FUNC)(const char **, T &, const std::string &); + PROPERTY_PARSER(T & v, FUNC f) : value(v), func(f) {} + PROPERTY_PARSER(T & v, FUNC f, const std::string & e) : value(v), func(f), encoding(e) {} + virtual bool Parse(const char ** attr, const std::string & attrName, const std::string & /*fromEncoding*/) { return func(attr, value, attrName); } + private: + T & value; + FUNC func; + std::string encoding; +}; + +template <> +inline +bool PROPERTY_PARSER::Parse(const char ** attr, const std::string & attrName, const std::string & toEncoding) +{ +if (!encoding.empty() && !toEncoding.empty()) + { + std::string tmp; + if (!func(attr, tmp, attrName)) + return false; + value = IconvString(tmp, encoding, toEncoding); + return true; + } +else + return func(attr, value, attrName); +} + +typedef std::map PROPERTY_PARSERS; + +bool CheckValue(const char ** attr, const std::string & attrName); + +template +inline +bool GetValue(const char ** attr, T & value, const std::string & attrName) +{ +if (CheckValue(attr, attrName)) + if (str2x(attr[1], value) < 0) + return false; +return true; +} + +template <> +inline +bool GetValue(const char ** attr, std::string & value, const std::string & attrName) +{ +if (!CheckValue(attr, attrName)) + return false; +value = attr[1]; +return true; +} + +template <> +inline +bool GetValue(const char ** attr, double & value, const std::string & attrName) +{ +if (CheckValue(attr, attrName)) + if (strtodouble2(attr[1], value)) + return false; +return true; +} + +bool GetEncodedValue(const char ** attr, std::string & value, const std::string & attrName); + +bool GetIPValue(const char ** attr, uint32_t& value, const std::string & attrName); + +template +inline +void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const typename PROPERTY_PARSER::FUNC & func = GetValue) +{ + parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER(value, func))); +} + +template +inline +void AddParser(PROPERTY_PARSERS & parsers, const std::string & name, T & value, const std::string & toEncoding, const typename PROPERTY_PARSER::FUNC & func = GetValue) +{ + parsers.insert(std::make_pair(ToLower(name), new PROPERTY_PARSER(value, func, toEncoding))); +} + +bool TryParse(PROPERTY_PARSERS & parsers, const std::string & name, const char ** attr, const std::string & fromEncoding, const std::string & attrName = "value"); + +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/resetable_utils.h b/libs/srvconf/parsers/resetable_utils.h new file mode 100644 index 00000000..6f026adf --- /dev/null +++ b/libs/srvconf/parsers/resetable_utils.h @@ -0,0 +1,141 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_RESETABLE_UTILS_H__ +#define __STG_STGLIBS_SRVCONF_RESETABLE_UTILS_H__ + +#include "stg/resetable.h" +#include "stg/common.h" + +#include +#include + +namespace STG +{ + +template +inline +void appendTag(std::ostream & stream, const std::string & name, const T & value) +{ + stream << "<" << name << " value=\"" << value << "\"/>"; +} + +template +inline +void appendTag(std::ostream & stream, const std::string & name, size_t suffix, const T & value) +{ + stream << "<" << name << suffix << " value=\"" << value << "\"/>"; +} + +template <> +inline +void appendTag(std::ostream & stream, const std::string & name, const uint8_t & value) +{ + stream << "<" << name << " value=\"" << static_cast(value) << "\"/>"; +} + +template <> +inline +void appendTag(std::ostream & stream, const std::string & name, const int8_t & value) +{ + stream << "<" << name << " value=\"" << static_cast(value) << "\"/>"; +} + +template +inline +void appendAttr(std::ostream & stream, const std::string & name, const T & value) +{ + stream << " " << name << "=\"" << value << "\""; +} + +template +inline +void appendAttr(std::ostream & stream, const std::string & name, size_t suffix, const T & value) +{ + stream << " " << name << suffix << "=\"" << value << "\""; +} + +template <> +inline +void appendAttr(std::ostream & stream, const std::string & name, const uint8_t & value) +{ + stream << " " << name << "=\"" << static_cast(value) << "\""; +} + +template <> +inline +void appendAttr(std::ostream & stream, const std::string & name, const int8_t & value) +{ + stream << " " << name << "=\"" << static_cast(value) << "\""; +} + +template +inline +void appendResetableTag(std::ostream & stream, const std::string & name, const T & value) +{ +if (!value.empty()) + appendTag(stream, name, value.const_data()); +} + +template +inline +void appendResetableTag(std::ostream & stream, const std::string & name, size_t suffix, const T & value) +{ +if (!value.empty()) + appendTag(stream, name, suffix, value.const_data()); +} + +template +inline +void appendResetableAttr(std::ostream & stream, const std::string & name, const T & value) +{ +if (!value.empty()) + appendAttr(stream, name, value.const_data()); +} + +template +inline +void appendResetableAttr(std::ostream & stream, const std::string & name, size_t suffix, const T & value) +{ +if (!value.empty()) + appendAttr(stream, name, suffix, value.const_data()); +} + +inline +RESETABLE MaybeEncode(const RESETABLE & value) +{ +RESETABLE res; +if (!value.empty()) + res = Encode12str(value.data()); +return res; +} + +inline +RESETABLE MaybeIconv(const RESETABLE & value, const std::string & fromEncoding, const std::string & toEncoding) +{ +RESETABLE res; +if (!value.empty()) + res = IconvString(value.data(), fromEncoding, toEncoding); +return res; +} + +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/server_info.cpp b/libs/srvconf/parsers/server_info.cpp new file mode 100644 index 00000000..f0033611 --- /dev/null +++ b/libs/srvconf/parsers/server_info.cpp @@ -0,0 +1,77 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#include "server_info.h" + +#include "stg/common.h" + +#include // sprintf + +#include + +using namespace STG; + +SERVER_INFO::PARSER::PARSER(CALLBACK f, void * d, const std::string & e) + : callback(f), + data(d), + encoding(e), + depth(0), + parsingAnswer(false) +{ + AddParser(propertyParsers, "uname", info.uname); + AddParser(propertyParsers, "version", info.version); + AddParser(propertyParsers, "tariff", info.tariffType); + AddParser(propertyParsers, "dir_num", info.dirNum); + AddParser(propertyParsers, "user_num", info.usersNum); + AddParser(propertyParsers, "tariff_num", info.tariffNum); + + for (size_t i = 0; i < DIR_NUM; i++) + AddParser(propertyParsers, "dir_name_" + unsigned2str(i), info.dirName[i], GetEncodedValue); +} +//----------------------------------------------------------------------------- +int SERVER_INFO::PARSER::ParseStart(const char *el, const char **attr) +{ +depth++; +if (depth == 1) + { + if (strcasecmp(el, "GetServerInfo") == 0) + parsingAnswer = true; + } +else + { + if (depth == 2 && parsingAnswer) + if (!TryParse(propertyParsers, ToLower(el), attr, encoding)) + error = "Invalid parameter."; + } +return 0; +} +//----------------------------------------------------------------------------- +void SERVER_INFO::PARSER::ParseEnd(const char * /*el*/) +{ +depth--; +if (depth == 0 && parsingAnswer) + { + if (callback) + callback(error.empty(), error, info, data); + error.clear(); + parsingAnswer = false; + } +} diff --git a/libs/srvconf/parsers/server_info.h b/libs/srvconf/parsers/server_info.h new file mode 100644 index 00000000..03906389 --- /dev/null +++ b/libs/srvconf/parsers/server_info.h @@ -0,0 +1,59 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_SERVER_INFO_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_SERVER_INFO_H__ + +#include "base.h" +#include "property.h" + +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace SERVER_INFO +{ + +class PARSER: public STG::PARSER +{ +public: + PARSER(CALLBACK f, void * data, const std::string & encoding); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, info, data); } + +private: + PROPERTY_PARSERS propertyParsers; + CALLBACK callback; + void * data; + std::string encoding; + int depth; + bool parsingAnswer; + INFO info; + std::string error; +}; + +} // namespace SERVER_INFO +} // namespace STG + +#endif diff --git a/libs/srvconf/parsers/simple.cpp b/libs/srvconf/parsers/simple.cpp new file mode 100644 index 00000000..4749c70f --- /dev/null +++ b/libs/srvconf/parsers/simple.cpp @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#include "simple.h" + +#include + +using namespace STG; + +SIMPLE::PARSER::PARSER(const std::string & t, CALLBACK f, void * d, const std::string & e) + : tag(t), + callback(f), + data(d), + encoding(e), + depth(0) +{ +} +//----------------------------------------------------------------------------- +int SIMPLE::PARSER::ParseStart(const char *el, const char **attr) +{ +depth++; +if (depth == 1) + if (strcasecmp(el, tag.c_str()) == 0) + ParseAnswer(el, attr); +return 0; +} +//----------------------------------------------------------------------------- +void SIMPLE::PARSER::ParseEnd(const char *) +{ +depth--; +} +//----------------------------------------------------------------------------- +void SIMPLE::PARSER::ParseAnswer(const char * /*el*/, const char ** attr) +{ +if (!callback) + return; +if (attr && attr[0] && attr[1]) + callback(strcasecmp(attr[1], "ok") == 0, attr[2] && attr[3] ? attr[3] : attr[1], data); +else + callback(false, "Invalid response.", data); +} diff --git a/libs/srvconf/parsers/simple.h b/libs/srvconf/parsers/simple.h new file mode 100644 index 00000000..244e8ef0 --- /dev/null +++ b/libs/srvconf/parsers/simple.h @@ -0,0 +1,56 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Maxim Mamontov + */ + +#ifndef __STG_STGLIBS_SRVCONF_PARSER_SIMPLE_H__ +#define __STG_STGLIBS_SRVCONF_PARSER_SIMPLE_H__ + +#include "base.h" + +#include "stg/servconf_types.h" + +#include + +namespace STG +{ +namespace SIMPLE +{ + +class PARSER: public STG::PARSER +{ +public: + PARSER(const std::string & tag, CALLBACK f, void * data, const std::string & encoding); + int ParseStart(const char * el, const char ** attr); + void ParseEnd(const char * el); + void Failure(const std::string & reason) { callback(false, reason, data); } + +private: + std::string tag; + CALLBACK callback; + void * data; + std::string encoding; + int depth; + + void ParseAnswer(const char * el, const char ** attr); +}; + +} // namespace SIMPLE +} // namespace STG + +#endif diff --git a/libs/srvconf/servconf.cpp b/libs/srvconf/servconf.cpp new file mode 100644 index 00000000..046190ee --- /dev/null +++ b/libs/srvconf/servconf.cpp @@ -0,0 +1,421 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Author : Boris Mikhailenko + * Author : Maxim Mamontov + */ + +#include "stg/servconf.h" + +#include "netunit.h" + +#include "parsers/simple.h" +#include "parsers/get_container.h" + +#include "parsers/server_info.h" + +#include "parsers/get_admin.h" +#include "parsers/chg_admin.h" + +#include "parsers/get_tariff.h" +#include "parsers/chg_tariff.h" + +#include "parsers/auth_by.h" +#include "parsers/get_user.h" +#include "parsers/chg_user.h" + +#include "parsers/get_service.h" +#include "parsers/chg_service.h" + +#include "parsers/get_corp.h" +#include "parsers/chg_corp.h" + +#include "parsers/base.h" + +#include "stg/common.h" + +#include +#include +#include + +#include +#include + +using namespace STG; + +class SERVCONF::IMPL +{ +public: + IMPL(const std::string & server, uint16_t port, + const std::string & login, const std::string & password); + IMPL(const std::string & server, uint16_t port, + const std::string & localAddress, uint16_t localPort, + const std::string & login, const std::string & password); + ~IMPL() { XML_ParserFree(parser); } + + const std::string & GetStrError() const; + static void Start(void * data, const char * el, const char ** attr); + static void End(void * data, const char * el); + + int RawXML(const std::string & request, RAW_XML::CALLBACK f, void * data); + + template + int Exec(const std::string & request, C callback, void * data) + { + P cp(callback, data, encoding); + return ExecImpl(request, cp); + } + + template + int Exec(const std::string & tag, const std::string & request, C callback, void * data) + { + P cp(tag, callback, data, encoding); + return ExecImpl(request, cp); + } + + const std::string & Encoding() const { return encoding; } + +private: + NETTRANSACT nt; + + std::string encoding; + std::string errorMsg; + XML_Parser parser; + + static bool ParserRecv(const std::string & chunk, bool final, void * data); + static bool SimpleRecv(const std::string & chunk, bool final, void * data); + int ExecImpl(const std::string & request, PARSER & cp); +}; + +bool SERVCONF::IMPL::ParserRecv(const std::string & chunk, bool final, void * data) +{ +SERVCONF::IMPL * sc = static_cast(data); + +if (XML_Parse(sc->parser, chunk.c_str(), chunk.length(), final) == XML_STATUS_ERROR) + { + strprintf(&sc->errorMsg, "XML parse error at line %d, %d: %s. Is final: %d", + static_cast(XML_GetCurrentLineNumber(sc->parser)), + static_cast(XML_GetCurrentColumnNumber(sc->parser)), + XML_ErrorString(XML_GetErrorCode(sc->parser)), (int)final); + return false; + } + +return true; +} + +bool SERVCONF::IMPL::SimpleRecv(const std::string & chunk, bool /*final*/, void * data) +{ +*static_cast(data) += chunk; +return true; +} + +SERVCONF::SERVCONF(const std::string & server, uint16_t port, + const std::string & login, const std::string & password) + : pImpl(new IMPL(server, port, login, password)) +{ +} + +SERVCONF::SERVCONF(const std::string & server, uint16_t port, + const std::string & localAddress, uint16_t localPort, + const std::string & login, const std::string & password) + : pImpl(new IMPL(server, port, localAddress, localPort, login, password)) +{ +} + +SERVCONF::~SERVCONF() +{ +delete pImpl; +} + +int SERVCONF::ServerInfo(SERVER_INFO::CALLBACK f, void * data) +{ +return pImpl->Exec("", f, data); +} + +int SERVCONF::RawXML(const std::string & request, RAW_XML::CALLBACK f, void * data) +{ +return pImpl->RawXML(request, f, data); +} + +// -- Admins -- + +int SERVCONF::GetAdmins(GET_CONTAINER::CALLBACK::TYPE f, void * data) +{ +return pImpl->Exec >("admins", "", f, data); +} + +int SERVCONF::GetAdmin(const std::string & login, GET_ADMIN::CALLBACK f, void * data) +{ +return pImpl->Exec("", f, data); +} + +int SERVCONF::ChgAdmin(const ADMIN_CONF_RES & conf, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("ChgAdmin", "Encoding()) + "/>", f, data); +} + +int SERVCONF::AddAdmin(const std::string & login, + const ADMIN_CONF_RES & conf, + SIMPLE::CALLBACK f, void * data) +{ +int res = pImpl->Exec("AddAdmin", "", f, data); +if (res != st_ok) + return res; +return pImpl->Exec("ChgAdmin", "Encoding()) + "/>", f, data); +} + +int SERVCONF::DelAdmin(const std::string & login, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("DelAdmin", "", f, data); +} + +// -- Tariffs -- + +int SERVCONF::GetTariffs(GET_CONTAINER::CALLBACK::TYPE f, void * data) +{ +return pImpl->Exec >("tariffs", "", f, data); +} + +int SERVCONF::GetTariff(const std::string & name, GET_TARIFF::CALLBACK f, void * data) +{ +return pImpl->Exec("", f, data); +} + +int SERVCONF::ChgTariff(const TARIFF_DATA_RES & tariffData, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("SetTariff", "" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "", f, data); +} + +int SERVCONF::AddTariff(const std::string & name, + const TARIFF_DATA_RES & tariffData, + SIMPLE::CALLBACK f, void * data) +{ +int res = pImpl->Exec("AddTariff", "", f, data); +if (res != st_ok) + return res; +return pImpl->Exec("SetTariff", "" + CHG_TARIFF::Serialize(tariffData, pImpl->Encoding()) + "", f, data); +} + +int SERVCONF::DelTariff(const std::string & name, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("DelTariff", "", f, data); +} + +// -- Users -- + +int SERVCONF::GetUsers(GET_CONTAINER::CALLBACK::TYPE f, void * data) +{ +return pImpl->Exec >("users", "", f, data); +} + +int SERVCONF::GetUser(const std::string & login, GET_USER::CALLBACK f, void * data) +{ +return pImpl->Exec("", f, data); +} + +int SERVCONF::ChgUser(const std::string & login, + const USER_CONF_RES & conf, + const USER_STAT_RES & stat, + SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "", f, data); +} + +int SERVCONF::DelUser(const std::string & login, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("DelUser", "", f, data); +} + +int SERVCONF::AddUser(const std::string & login, + const USER_CONF_RES & conf, + const USER_STAT_RES & stat, + SIMPLE::CALLBACK f, void * data) +{ +int res = pImpl->Exec("AddUser", "", f, data); +if (res != st_ok) + return res; +return pImpl->Exec("" + CHG_USER::Serialize(conf, stat, pImpl->Encoding()) + "", f, data); +} + +int SERVCONF::AuthBy(const std::string & login, AUTH_BY::CALLBACK f, void * data) +{ +return pImpl->Exec("", f, data); +} + +int SERVCONF::SendMessage(const std::string & login, const std::string & text, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("SendMessageResult", "", f, data); +} + +int SERVCONF::CheckUser(const std::string & login, const std::string & password, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("CheckUser", "", f, data); +} + +// -- Services -- + +int SERVCONF::GetServices(GET_CONTAINER::CALLBACK::TYPE f, void * data) +{ +return pImpl->Exec >("services", "", f, data); +} + +int SERVCONF::GetService(const std::string & name, GET_SERVICE::CALLBACK f, void * data) +{ +return pImpl->Exec("", f, data); +} + +int SERVCONF::ChgService(const SERVICE_CONF_RES & conf, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("SetService", "Encoding()) + "/>", f, data); +} + +int SERVCONF::AddService(const std::string & name, + const SERVICE_CONF_RES & conf, + SIMPLE::CALLBACK f, void * data) +{ +int res = pImpl->Exec("AddService", "", f, data); +if (res != st_ok) + return res; +return pImpl->Exec("SetService", "Encoding()) + "/>", f, data); +} + +int SERVCONF::DelService(const std::string & name, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("DelService", "", f, data); +} + +// -- Corporations -- + +int SERVCONF::GetCorporations(GET_CONTAINER::CALLBACK::TYPE f, void * data) +{ +return pImpl->Exec >("corporations", "", f, data); +} + +int SERVCONF::GetCorp(const std::string & name, GET_CORP::CALLBACK f, void * data) +{ +return pImpl->Exec("", f, data); +} + +int SERVCONF::ChgCorp(const CORP_CONF_RES & conf, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("SetCorp", "" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "", f, data); +} + +int SERVCONF::AddCorp(const std::string & name, + const CORP_CONF_RES & conf, + SIMPLE::CALLBACK f, void * data) +{ +int res = pImpl->Exec("AddCorp", "", f, data); +if (res != st_ok) + return res; +return pImpl->Exec("SetCorp", "" + CHG_CORP::Serialize(conf, pImpl->Encoding()) + "", f, data); +} + +int SERVCONF::DelCorp(const std::string & name, SIMPLE::CALLBACK f, void * data) +{ +return pImpl->Exec("DelCorp", "", f, data); +} + +const std::string & SERVCONF::GetStrError() const +{ +return pImpl->GetStrError(); +} + +//----------------------------------------------------------------------------- +SERVCONF::IMPL::IMPL(const std::string & server, uint16_t port, + const std::string & login, const std::string & password) + : nt(server, port, login, password) +{ +setlocale(LC_ALL, ""); +setlocale(LC_NUMERIC, "C"); +encoding = nl_langinfo(CODESET); +parser = XML_ParserCreate(NULL); +} +//----------------------------------------------------------------------------- +SERVCONF::IMPL::IMPL(const std::string & server, uint16_t port, + const std::string & localAddress, uint16_t localPort, + const std::string & login, const std::string & password) + : nt(server, port, localAddress, localPort, login, password) +{ +setlocale(LC_ALL, ""); +setlocale(LC_NUMERIC, "C"); +encoding = nl_langinfo(CODESET); +parser = XML_ParserCreate(NULL); +} +//----------------------------------------------------------------------------- +void SERVCONF::IMPL::Start(void * data, const char * el, const char ** attr) +{ +PARSER * currParser = static_cast(data); +currParser->ParseStart(el, attr); +} +//----------------------------------------------------------------------------- +void SERVCONF::IMPL::End(void * data, const char * el) +{ +PARSER * currParser = static_cast(data); +currParser->ParseEnd(el); +} +//----------------------------------------------------------------------------- +const std::string & SERVCONF::IMPL::GetStrError() const +{ +return errorMsg; +} +//----------------------------------------------------------------------------- +int SERVCONF::IMPL::ExecImpl(const std::string & request, PARSER & cp) +{ +XML_ParserReset(parser, NULL); +XML_SetElementHandler(parser, Start, End); +XML_SetUserData(parser, &cp); + +int ret = 0; +if ((ret = nt.Connect()) != st_ok) + { + errorMsg = nt.GetError(); + cp.Failure(errorMsg); + return ret; + } +if ((ret = nt.Transact(request, ParserRecv, this)) != st_ok) + { + errorMsg = nt.GetError(); + cp.Failure(errorMsg); + return ret; + } + +nt.Disconnect(); +return st_ok; +} + +int SERVCONF::IMPL::RawXML(const std::string & request, RAW_XML::CALLBACK callback, void * data) +{ +int ret = 0; +if ((ret = nt.Connect()) != st_ok) + { + errorMsg = nt.GetError(); + callback(false, errorMsg, "", data); + return ret; + } +std::string response; +if ((ret = nt.Transact(request, SimpleRecv, &response)) != st_ok) + { + errorMsg = nt.GetError(); + callback(false, errorMsg, "", data); + return ret; + } + +nt.Disconnect(); +callback(true, "", response, data); +return st_ok; +} diff --git a/make_tarball/get_from_cvs b/make_tarball/get_from_cvs new file mode 100755 index 00000000..362f4029 --- /dev/null +++ b/make_tarball/get_from_cvs @@ -0,0 +1,58 @@ +#!/usr/bin/expect + +# login_cvs host password + +set user [lindex $argv 0] +set pass [lindex $argv 1] +set host [lindex $argv 2] +set cvsroot [lindex $argv 3] +set module [lindex $argv 4] +set dir [lindex $argv 5] + +set timeout 30 + +send_user "checkout module $module"; + +spawn ssh $user@$host +expect { + "(yes/no)? " { + send "yes\r" + send_user "Key accepted"; + } + "assword:" { + close + send_user "Key accepting dont needed"; + } + } + +spawn cvs -d :ext:$user@$host:$cvsroot co -N -d $dir $module +expect { + "assword:" { + send "$pass\r" + expect { + "assword:" { + send_user "

cvs checkout $module failed. Incorrect password

"; + exit 1 + } + "aborted" { + send_user "

cvs checkout $module failed.

"; + exit 1 + } + expect eof { + if {[lindex [wait] 3]} { + send_user "

cvs checkout $module failed.

" + exit 1 + } + } + } + } + + "aborted" { + send_user "

cvs checkout $module failed.

"; + exit 1 + } + } + + + + diff --git a/make_tarball/make.sh b/make_tarball/make.sh new file mode 100755 index 00000000..0c052724 --- /dev/null +++ b/make_tarball/make.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +SRC_DIR=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"` +ARC_NAME=$SRC_DIR.tar.gz + +git clone git://gitorious.org/stg/stg.git $SRC_DIR + +if [ $? != 0 ] +then + echo "Failed to clone repository" + exit -1 +fi + +rm -rf $SRC_DIR/.git +rm -f $SRC_DIR/.gitignore +rm -r $SRC_DIR/projects/make_tarball +rm -r $SRC_DIR/projects/traffcounter +rm -r $SRC_DIR/projects/sgauthstress +rm -r $SRC_DIR/projects/stargazer/plugins/authorization/stress +rm -r $SRC_DIR/projects/stargazer/plugins/configuration/sgconfig2 +rm -r $SRC_DIR/projects/stargazer/plugins/configuration/sgconfig-ng +rm -r $SRC_DIR/projects/stargazer/plugins/configuration/xrconfig +rm -r $SRC_DIR/projects/stargazer/plugins/other/userstat +rm -r $SRC_DIR/projects/stargazer/plugins/store/db +rm -r $SRC_DIR/doc/help +rm $SRC_DIR/doc/help.odt + +make -C $SRC_DIR/doc/xmlrpc + +tar -zcf $ARC_NAME $SRC_DIR diff --git a/make_tarball/mt.sh b/make_tarball/mt.sh new file mode 100755 index 00000000..bbfa45a1 --- /dev/null +++ b/make_tarball/mt.sh @@ -0,0 +1,59 @@ +#!/bin/bash + + +cvs_host=stgteam.dp.ua +cvs_user= +cvs_pass= + +#arc_name=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"`.tgz +#arc_name=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"`.tgz +src_dir=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"` +arc_name=$src_dir.tar.gz + +#mkdir $src_dir + +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stgincludes include $src_dir + +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/common.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/ibpp.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/common_settings.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/conffiles.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/crypto.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/logger.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/locker.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/hostallow.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/pinger.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/dotconfpp.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/ia_auth_c.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/script_executer.lib $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/srvconf.lib $src_dir + +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/Makefile $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/Makefile.in $src_dir +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer convertor $src_dir/projects +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer stargazer $src_dir/projects + +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/sgauth sgauth $src_dir/projects +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/sgconf sgconf $src_dir/projects +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/rscriptd rscriptd $src_dir/projects +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer rlm_stg $src_dir/projects + +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stgplugins plugins/store/firebird $src_dir/projects/stargazer +./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stg3plugins max_mods/mysql $src_dir/projects/stargazer/plugins/store +mv $src_dir/projects/stargazer/plugins/store/max_mods/mysql $src_dir/projects/stargazer/plugins/store/ +rm -rf $src_dir/projects/stargazer/plugins/store/max_mods +rm -rf $src_dir/projects/stargazer/plugins/other/userstat +rm -rf $src_dir/projects/stargazer/plugins/authorization/stress +rm -rf $src_dir/projects/stargazer/plugins/store/db +rm -rf $src_dir/projects/stargazer/plugins/configuration/rpcconfig + +rm -f $src_dir/include/lp2_blocks.h +rm -f $src_dir/include/stdstring.h + +mkdir -p $src_dir/lib + +rm -fr $(find $src_dir/ -name CVS -type d) + +rm -fr $src_dir/projects/stargazer/inst/var/stargazer/users/CVS + +tar -czf $arc_name $src_dir diff --git a/projects/libs/Makefile b/projects/libs/Makefile deleted file mode 100644 index 675002e5..00000000 --- a/projects/libs/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# - -# -# Author : Maxim Mamontov -# - -include ../../Makefile.conf - -.PHONY: all clean distclean libs install uninstall install-bin -all: libs - -libs: - $(MAKE) -C $(DIR_LIBSRC) - -clean: - $(MAKE) -C $(DIR_LIBSRC) clean - -distclean: clean - rm -f ../../Makefile.conf - -install: install-bin install-data - -install-bin: $(PROG) - $(MAKE) -C $(DIR_INCLUDE) install - $(MAKE) -C $(DIR_LIBSRC) install - -uninstall: uninstall-bin - -uninstall-bin: - $(MAKE) -C $(DIR_LIBSRC) uninstall diff --git a/projects/libs/build b/projects/libs/build deleted file mode 100755 index 4c1fce9b..00000000 --- a/projects/libs/build +++ /dev/null @@ -1,289 +0,0 @@ -#!/bin/sh - -# Installation path prefix - -#PREFIX="" - -# Binaries access bits - -BIN_MODE=0755 - -# Data files access bits - -DATA_MODE=0644 - -# Dir access bits - -DIR_MODE=0755 - -# Binaries and data files owner - -OWNER=root - -OS=unknown -sys=`uname -s` -release=`uname -r` -major=`printf "%s" "$release" | cut -d. -f1` -BUILD_DIR=`pwd` -CONFFILE="../../Makefile.conf" - - -if [ "$1" = "debug" ] -then - DEFS="$DEFS -DDEBUG" - MAKEOPTS="$MAKEOPTS -j1" - CFLAGS="$CFLAGS -ggdb3 -W -Wall" - CXXFLAGS="$CXXFLAGS -ggdb3 -W -Wall" - DEBUG="yes" -else - DEFS="$DEFS -DNDEBUG" - DEBUG="no" -fi - -CFLAGS="$CFLAGS -I/usr/local/include" -CXXFLAGS="$CXXFLAGS -I/usr/local/include" -LDFLAGS="$LDFLAGS -L/usr/local/lib" - -if [ "$sys" = "Linux" ] -then - OS=linux - MAKE="make" -fi - -if [ "$sys" = "FreeBSD" ] -then - case $major in - 4) OS=bsd;; - 5) OS=bsd5;; - 6) OS=bsd5;; - 7) OS=bsd7;; - *) OS=bsd7;; - esac - MAKE="gmake" -fi - -if [ "$sys" = "Darwin" ] -then - OS=darwin - MAKE="gmake" -fi - -if [ "$OS" = "unknown" ] -then - printf "#############################################################################\n" - printf "# Sorry, but we currently support Linux, FreeBSD and Darwin. #\n" - printf "#############################################################################\n" - exit 1 -fi - -printf "#############################################################################\n" -printf " Building STG 2.4 libs for $sys $release\n" -printf "#############################################################################\n" - -STG_LIBS="logger.lib - crypto.lib - common.lib - scriptexecuter.lib - conffiles.lib - pinger.lib - dotconfpp.lib - smux.lib - ia.lib - srvconf.lib" - -if [ "$OS" = "linux" ] -then - DEFS="$DEFS -DLINUX" -else - LIBICONV="-liconv" - if [ "$OS" = "bsd" ] - then - DEFS="$DEFS -DFREE_BSD" - else - if [ "$OS" = "bsd7" ] - then - DEFS="$DEFS -DFREE_BSD5" - else - if [ "$OS" == "darwin" ] - then - DEFS="$DEFS -DDARWIN" - fi - fi - fi -fi - -if [ -z "$CC" ] -then - CC=gcc -fi - -if [ -z "$CXX" ] -then - CXX=g++ -fi - -printf "Checking CC... " -$CC --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CC not found\n" - exit; -fi -printf "found\n" -printf "Checking CXX... " -$CXX --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CXX not found\n" - exit; -fi -printf "found\n" - -printf "Checking endianess... " -printf "int main() { int probe = 0x00000001; return *(char *)&probe; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -o fake -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "Endianess checking failed\n" - exit; -else - ./fake - if [ $? = 1 ] - then - ARCH=le - CXXFLAGS="$CXXFLAGS -DARCH_LE" - CFLAGS="$CFLAGS -DARCH_LE" - printf "Little Endian\n" - else - ARCH=be - CXXFLAGS="$CXXFLAGS -DARCH_BE" - CFLAGS="$CFLAGS -DARCH_BE" - printf "Big Endian\n" - fi -fi -rm -f fake - -printf "Checking for -lexpat... " -printf "#include \nint main() { return 0; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -lexpat -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - CHECK_EXPAT=no - printf "no\n" -else - CHECK_EXPAT=yes - printf "yes\n" -fi -rm -f fake - -printf "Checking for iconv 2nd argument... " -printf "#include \nint main(){ const char** src = 0; iconv(0, src, 0, 0, 0); }\n" > build_check.c -$CC $CFLAGS $LDFLAGS -Werror build_check.c $LIBICONV -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "non-const\n" -else - DEFS="$DEFS -DCONST_ICONV" - printf "const\n" -fi -rm -f fake - -printf "Checking for fb_config... " -FB_VERSION=`fb_config --version 2> /dev/null` -if [ "$?" != "0" ] -then - printf "no\n" - printf "Checking for -lfbclient... " - printf "int main() { return 0; }\n" > build_check.c - $CC $CFLAGS $LDFLAGS build_check.c -lfbclient $LIB_THREAD -o fake > /dev/null 2> /dev/null - if [ $? != 0 ] - then - CHECK_FBCLIENT=no - printf "no\n" - else - FB_CFLAGS="" - FB_LDFLAGS="-lfbclient" - CHECK_FBCLIENT=yes - printf "yes\n" - fi - rm -f fake -else - printf "yes\n" - printf "Checking for fb_config --cflags... " - FB_CFLAGS=`fb_config --cflags` - if [ "$?" != "0" ] - then - CHECK_FBCLIENT=no - printf "no\n" - else - printf "[$FB_CFLAGS]\n" - printf "Checking for fb_config --libs " - FB_LDFLAGS=`fb_config --libs` - if [ "$?" != "0" ] - then - CHECK_FBCLIENT=no - printf "no\n" - else - CHECK_FBCLIENT=yes - printf "[$FB_LDFLAGS]\n" - fi - fi -fi - -rm -f build_check.c - -if [ "$CHECK_EXPAT" != "yes" ] -then - printf -- "-lexpat not found!\n" - exit 1 -fi - -if [ "$CHECK_FBCLIENT" = "yes" ] -then - STG_LIBS="$STG_LIBS - ibpp.lib" -fi - -printf "OS=$OS\n" > $CONFFILE -printf "STG_TIME=yes\n" >> $CONFFILE -printf "DEBUG=$DEBUG\n" >> $CONFFILE -printf "DIR_BUILD=$BUILD_DIR\n" >> $CONFFILE -printf "DIR_LIB=\$(DIR_BUILD)/../../lib\n" >> $CONFFILE -printf "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs\n" >> $CONFFILE -printf "DIR_INCLUDE=\$(DIR_BUILD)/../../include\n" >> $CONFFILE -printf "ARCH=$ARCH\n" >> $CONFFILE -printf "CHECK_EXPAT=$CHECK_EXPAT\n" >> $CONFFILE -printf "CHECK_FBCLIENT=$CHECK_FBCLIENT\n" >> $CONFFILE -if [ "$CHECK_FBCLIENT" = "yes" ] -then - printf "FB_CFLAGS=$FB_CFLAGS\n" >> $CONFFILE - printf "FB_LDFLAGS=$FB_LDFLAGS\n" >> $CONFFILE -fi -printf "DEFS=$DEFS\n" >> $CONFFILE -printf "STG_LIBS=" >> $CONFFILE -for lib in $STG_LIBS -do - printf "$lib " >> $CONFFILE -done -printf "\n" >> $CONFFILE -printf "CC=$CC\n" >> $CONFFILE -printf "CXX=$CXX\n" >> $CONFFILE -printf "CXXFLAGS=$CXXFLAGS\n" >> $CONFFILE -printf "CFLAGS=$CFLAGS\n" >> $CONFFILE -printf "LDFLAGS=$LDFLAGS\n" >> $CONFFILE -printf "LIBICONV=$LIBICONV\n" >> $CONFFILE -printf "PREFIX=$PREFIX\n" >> $CONFFILE -printf "BIN_MODE=$BIN_MODE\n" >> $CONFFILE -printf "DATA_MODE=$DATA_MODE\n" >> $CONFFILE -printf "DIR_MODE=$DIR_MODE\n" >> $CONFFILE -printf "OWNER=$OWNER\n" >> $CONFFILE - -if [ "$1" != "debug" ] -then - $MAKE $MAKEOPTS -else - printf "\n\n\nDebug build. Type $MAKE explicitly\n" -fi diff --git a/projects/make_tarball/get_from_cvs b/projects/make_tarball/get_from_cvs deleted file mode 100755 index 362f4029..00000000 --- a/projects/make_tarball/get_from_cvs +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/expect - -# login_cvs host password - -set user [lindex $argv 0] -set pass [lindex $argv 1] -set host [lindex $argv 2] -set cvsroot [lindex $argv 3] -set module [lindex $argv 4] -set dir [lindex $argv 5] - -set timeout 30 - -send_user "checkout module $module"; - -spawn ssh $user@$host -expect { - "(yes/no)? " { - send "yes\r" - send_user "Key accepted"; - } - "assword:" { - close - send_user "Key accepting dont needed"; - } - } - -spawn cvs -d :ext:$user@$host:$cvsroot co -N -d $dir $module -expect { - "assword:" { - send "$pass\r" - expect { - "assword:" { - send_user "

cvs checkout $module failed. Incorrect password

"; - exit 1 - } - "aborted" { - send_user "

cvs checkout $module failed.

"; - exit 1 - } - expect eof { - if {[lindex [wait] 3]} { - send_user "

cvs checkout $module failed.

" - exit 1 - } - } - } - } - - "aborted" { - send_user "

cvs checkout $module failed.

"; - exit 1 - } - } - - - - diff --git a/projects/make_tarball/make.sh b/projects/make_tarball/make.sh deleted file mode 100755 index 0c052724..00000000 --- a/projects/make_tarball/make.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh - -SRC_DIR=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"` -ARC_NAME=$SRC_DIR.tar.gz - -git clone git://gitorious.org/stg/stg.git $SRC_DIR - -if [ $? != 0 ] -then - echo "Failed to clone repository" - exit -1 -fi - -rm -rf $SRC_DIR/.git -rm -f $SRC_DIR/.gitignore -rm -r $SRC_DIR/projects/make_tarball -rm -r $SRC_DIR/projects/traffcounter -rm -r $SRC_DIR/projects/sgauthstress -rm -r $SRC_DIR/projects/stargazer/plugins/authorization/stress -rm -r $SRC_DIR/projects/stargazer/plugins/configuration/sgconfig2 -rm -r $SRC_DIR/projects/stargazer/plugins/configuration/sgconfig-ng -rm -r $SRC_DIR/projects/stargazer/plugins/configuration/xrconfig -rm -r $SRC_DIR/projects/stargazer/plugins/other/userstat -rm -r $SRC_DIR/projects/stargazer/plugins/store/db -rm -r $SRC_DIR/doc/help -rm $SRC_DIR/doc/help.odt - -make -C $SRC_DIR/doc/xmlrpc - -tar -zcf $ARC_NAME $SRC_DIR diff --git a/projects/make_tarball/mt.sh b/projects/make_tarball/mt.sh deleted file mode 100755 index bbfa45a1..00000000 --- a/projects/make_tarball/mt.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash - - -cvs_host=stgteam.dp.ua -cvs_user= -cvs_pass= - -#arc_name=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"`.tgz -#arc_name=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"`.tgz -src_dir=stg-2.4-`date "+%Y.%m.%d-%H.%M.%S"` -arc_name=$src_dir.tar.gz - -#mkdir $src_dir - -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stgincludes include $src_dir - -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/common.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/ibpp.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/common_settings.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/conffiles.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/crypto.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/logger.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/locker.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/hostallow.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/pinger.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/dotconfpp.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/ia_auth_c.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/script_executer.lib $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/srvconf.lib $src_dir - -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/Makefile $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stglibs stglibs/Makefile.in $src_dir -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer convertor $src_dir/projects -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer stargazer $src_dir/projects - -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/sgauth sgauth $src_dir/projects -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/sgconf sgconf $src_dir/projects -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/rscriptd rscriptd $src_dir/projects -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stargazer rlm_stg $src_dir/projects - -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stgplugins plugins/store/firebird $src_dir/projects/stargazer -./get_from_cvs $cvs_user $cvs_pass $cvs_host /cvsroot/stg3plugins max_mods/mysql $src_dir/projects/stargazer/plugins/store -mv $src_dir/projects/stargazer/plugins/store/max_mods/mysql $src_dir/projects/stargazer/plugins/store/ -rm -rf $src_dir/projects/stargazer/plugins/store/max_mods -rm -rf $src_dir/projects/stargazer/plugins/other/userstat -rm -rf $src_dir/projects/stargazer/plugins/authorization/stress -rm -rf $src_dir/projects/stargazer/plugins/store/db -rm -rf $src_dir/projects/stargazer/plugins/configuration/rpcconfig - -rm -f $src_dir/include/lp2_blocks.h -rm -f $src_dir/include/stdstring.h - -mkdir -p $src_dir/lib - -rm -fr $(find $src_dir/ -name CVS -type d) - -rm -fr $src_dir/projects/stargazer/inst/var/stargazer/users/CVS - -tar -czf $arc_name $src_dir diff --git a/projects/rlm_stg/Makefile b/projects/rlm_stg/Makefile deleted file mode 100644 index 27f486b4..00000000 --- a/projects/rlm_stg/Makefile +++ /dev/null @@ -1,116 +0,0 @@ -############################################################################### -# $Id: Makefile,v 1.5 2009/03/03 15:49:34 faust Exp $ -############################################################################### - -include ../../Makefile.conf - -LIB_NAME = rlm_stg - -PROG = $(LIB_NAME).so - -SRCS = rlm_stg.c \ - iface.cpp \ - stg_client.cpp \ - conn.cpp \ - radlog.c - -STGLIBS = crypto \ - common \ - json - -STGLIBS_INCS = $(addprefix -I ../../stglibs/,$(addsuffix .lib/include,$(STGLIBS))) -STGLIBS_LIBS = $(addprefix -L ../../stglibs/,$(addsuffix .lib,$(STGLIBS))) - -LIBS += $(addprefix -lstg,$(STGLIBS)) $(LIB_THREAD) $(LIBICONV) - -ifeq ($(OS),linux) -LIBS += -ldl \ - -lyajl -else -LIBS += -lintl \ - -lc \ - -lyajl -endif - -SEARCH_DIRS = -I ../../include - -OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))) - -CFLAGS += -fPIC $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -CXXFLAGS += -fPIC $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -CFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -LDFLAGS += -shared -Wl,-rpath,$(PREFIX)/usr/lib/stg -Wl,-E $(STGLIBS_LIBS) - -.PHONY: all clean distclean libs install uninstall install-bin uninstall-bin -all: libs $(PROG) ../../Makefile.conf - -libs: - $(MAKE) -C $(DIR_LIBSRC) - -$(PROG): $(OBJS) - $(CXX) $^ $(LDFLAGS) -o $(PROG) $(LIBS) - -clean: - rm -f deps $(PROG) *.o tags *.*~ .OS - rm -f .OS - rm -f core* - $(MAKE) -C $(DIR_LIBSRC) clean - -distclean: clean - rm -f ../../Makefile.conf - -install: install-bin - -install-bin: -ifeq ($(DEBUG), yes) -ifeq ($(OS), linux) - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib/freeradius - install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/lib/freeradius/$(PROG) -else - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib - install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/lib/$(PROG) -endif -else - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib/freeradius - install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/freeradius/$(PROG) -ifeq ($(OS), linux) - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib/freeradius - install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/freeradius/$(PROG) -else - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/lib - install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/lib/$(PROG) -endif -endif - $(MAKE) -C $(DIR_LIBSRC) install - -uninstall: uninstall-bin - -uninstall-bin: -ifeq ($(OS), linux) - rm -f $(PREFIX)/usr/lib/freeradius/$(PROG) -else - rm -f $(PREFIX)/usr/lib/$(PROG) -endif - -ifneq ($(MAKECMDGOALS),distclean) -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),uninstall) --include deps -endif -endif -endif - -deps: $(SRCS) ../../Makefile.conf - $(MAKE) -C $(DIR_LIBSRC) - @>deps ;\ - for file in $(SRCS); do\ - echo "$$file" | grep ".c$$" > /dev/null;\ - if [ $$? -eq 0 ];\ - then\ - echo "`$(CC) $(CFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CC) $(CFLAGS) -c $$<' >> deps ;\ - else\ - echo "`$(CXX) $(CXXFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CXX) $(CXXFLAGS) -c $$<' >> deps ;\ - fi;\ - done diff --git a/projects/rlm_stg/build b/projects/rlm_stg/build deleted file mode 100755 index 8d63ae64..00000000 --- a/projects/rlm_stg/build +++ /dev/null @@ -1,250 +0,0 @@ -#!/bin/sh - -# $Author: faust $ -# $Revision: 1.13 $ -# $Date: 2010/04/14 08:58:44 $ -###################################################### - -OS=unknown -sys=`uname -s` -release=`uname -r | cut -b1` -BUILD_DIR=`pwd` -CONFFILE="../../Makefile.conf" -PREFIX="/" -BIN_MODE=0755 -DATA_MODE=0644 -DIR_MODE=0755 -OWNER=root - -if [ "$1" = "debug" ] -then - DEFS="$DEFS -DDEBUG" - MAKEOPTS="$MAKEOPTS -j1" - CFLAGS="$CFLAGS -ggdb3 -W -Wall -Wextra" - CXXFLAGS="$CXXFLAGS -ggdb3 -W -Wall -Wextra" - DEBUG="yes" -else - DEFS="$DEFS -DNDEBUG" - DEBUG="no" -fi - -CFLAGS="$CFLAGS -I/usr/local/include" -CXXFLAGS="$CXXFLAGS -I/usr/local/include" -LDFLAGS="$LDFLAGS -L/usr/local/lib" - -if [ "$sys" = "Linux" ] -then - OS=linux - release="" - MAKE="make" -fi - -if [ "$sys" = "FreeBSD" ] -then - case $release in - 4) OS=bsd;; - 5) OS=bsd5;; - 6) OS=bsd5;; - 7) OS=bsd7;; - *) OS=bsd7;; - esac - MAKE="gmake" -fi - -if [ "$OS" = "unknown" ] -then - printf "#############################################################################\n" - printf "# Sorry, but rlm_stg currently supported by Linux, FreeBSD 4.x, 5.x, 6.x #\n" - printf "#############################################################################\n" - exit 1 -fi - -printf "#############################################################################\n" -printf " Building rlm_stg for $sys $release\n" -printf "#############################################################################\n" - -STG_LIBS="crypto.lib common.lib json.lib" - -if [ "$OS" = "linux" ] -then - DEFS="$DEFS -DLINUX" - LIB_THREAD=-lpthread -else - LIBICONV="-liconv" - if [ "$OS" = "bsd" ] - then - DEFS="$DEFS -DFREE_BSD" - else - DEFS="$DEFS -DFREE_BSD5" - if [ "$OS" = "bsd7" ] - then - LIB_THREAD=-lpthread - else - LIB_THREAD=-lc_r - fi - fi - CXXFLAGS="$CXXFLAGS -DHAVE_CLOSEFROM" -fi - -if [ -z "$CC" ] -then - CC=gcc -fi - -if [ -z "$CXX" ] -then - CXX=g++ -fi - -printf "Checking CC... " -$CC --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CC not found\n" - exit; -fi -printf "found\n" -printf "Checking CXX... " -$CXX --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CXX not found\n" - exit; -fi -printf "found\n" - -printf "Checking endianess... " -printf "int main() { int probe = 0x00000001; return *(char *)&probe; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "Endianess checking failed\n" - exit; -else - ./fake - if [ $? = 1 ] - then - ARCH=le - CXXFLAGS="$CXXFLAGS -DARCH_LE" - CFLAGS="$CFLAGS -DARCH_LE" - printf "Little Endian\n" - else - ARCH=be - CXXFLAGS="$CXXFLAGS -DARCH_BE" - CFLAGS="$CFLAGS -DARCH_BE" - printf "Big Endian\n" - fi -fi -rm -f fake - -printf "Checking for iconv 2nd argument... " -printf "#include \nint main(){ const char** src = 0; iconv(0, src, 0, 0, 0); }\n" > build_check.c -$CC $CFLAGS $LDFLAGS -Werror build_check.c $LIBICONV -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "non-const\n" -else - DEFS="$DEFS -DCONST_ICONV" - printf "const\n" -fi -rm -f fake - -printf "Checking for -lyajl... " -pkg-config --version > /dev/null 2> /dev/null -if [ "$?" = "0" ] -then - pkg-config --atleast-version=2.0.0 yajl - if [ "$?" != "0" ] - then - CHECK_YAJL=no - printf "no\n" - exit; - else - CHECK_YAJL=yes - printf `pkg-config --modversion yajl`"\n" - fi -else - printf "#include \n" > build_check.c - printf "#include \n" >> build_check.c - printf "int main() { printf(\"%%d\", yajl_version()); return 0; }\n" >> build_check.c - $CC $CFLAGS $LDFLAGS build_check.c -lyajl -o fake > /dev/null 2> /dev/null - if [ $? != 0 ] - then - CHECK_YAJL=no - printf "no\n" - exit; - else - YAJL_VERSION=`./fake` - if [ $YAJL_VERSION -ge 20000 ] - then - CHECK_YAJL=yes - printf "${YAJL_VERSION}\n" - else - CHECK_YAJL=no - printf "no. Need at least version 2.0.0, existing version is ${YAJL_VERSION}\n" - exit; - fi - fi - rm -f fake -fi - -printf "Checking for boost::scoped_ptr... " -printf "#include \nint main() { boost::scoped_ptr test(new int(1)); return 0; }\n" > build_check.cpp -$CXX $CXXFLAGS $LDFLAGS build_check.cpp -o fake # > /dev/null 2> /dev/null -if [ $? != 0 ] -then - CHECK_BOOST_SCOPED_PTR=no - printf "no\n" - exit; -else - CHECK_BOOST_SCOPED_PTR=yes - printf "yes\n" -fi -rm -f fake - -rm -f build_check.c -rm -f build_check.cpp - -if [ "$CHECK_YAJL" = "yes" -a "$CHECK_BOOST_SCOPED_PTR" = "yes" ] -then - STG_LIBS="$STG_LIBS - json.lib" -fi - -printf "OS=$OS\n" > $CONFFILE -printf "STG_TIME=yes\n" >> $CONFFILE -printf "DEBUG=$DEBUG\n" >> $CONFFILE -printf "DIR_BUILD=$BUILD_DIR\n" >> $CONFFILE -printf "DIR_LIB=\$(DIR_BUILD)/../../lib\n" >> $CONFFILE -printf "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs\n" >> $CONFFILE -printf "DIR_INCLUDE=\$(DIR_BUILD)/../../include\n" >> $CONFFILE -printf "ARCH=$ARCH\n" >> $CONFFILE -printf "DEFS=$DEFS\n" >> $CONFFILE -printf "STG_LIBS=" >> $CONFFILE -for lib in $STG_LIBS -do - printf "$lib " >> $CONFFILE -done -printf "\n" >> $CONFFILE -printf "CC=$CC\n" >> $CONFFILE -printf "CXX=$CXX\n" >> $CONFFILE -printf "CXXFLAGS=$CXXFLAGS\n" >> $CONFFILE -printf "CFLAGS=$CFLAGS\n" >> $CONFFILE -printf "LDFLAGS=$LDFLAGS\n" >> $CONFFILE -printf "LIB_THREAD=$LIB_THREAD\n" >> $CONFFILE -printf "LIBICONV=$LIBICONV\n" >> $CONFFILE -printf "PREFIX=$PREFIX\n" >> $CONFFILE -printf "BIN_MODE=$BIN_MODE\n" >> $CONFFILE -printf "DATA_MODE=$DATA_MODE\n" >> $CONFFILE -printf "DIR_MODE=$DIR_MODE\n" >> $CONFFILE -printf "OWNER=$OWNER\n" >> $CONFFILE - -if [ "$1" != "debug" ] -then - $MAKE $MAKEOPTS -else - printf "\n\n\nDebug build. Type $MAKE explicitly\n" -fi diff --git a/projects/rlm_stg/conn.cpp b/projects/rlm_stg/conn.cpp deleted file mode 100644 index 3589a901..00000000 --- a/projects/rlm_stg/conn.cpp +++ /dev/null @@ -1,686 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#include "conn.h" - -#include "radlog.h" -#include "stgpair.h" - -#include "stg/json_parser.h" -#include "stg/json_generator.h" -#include "stg/locker.h" - -#include -#include - -#include -#include -#include // UNIX -#include // IP -#include // TCP -#include - -namespace RLM = STG::RLM; - -using RLM::Conn; -using STG::JSON::Parser; -using STG::JSON::PairsParser; -using STG::JSON::EnumParser; -using STG::JSON::NodeParser; -using STG::JSON::Gen; -using STG::JSON::MapGen; -using STG::JSON::StringGen; - -namespace -{ - -double CONN_TIMEOUT = 60; -double PING_TIMEOUT = 10; - -struct ChannelConfig { - struct Error : std::runtime_error { - explicit Error(const std::string& message) : runtime_error(message) {} - }; - - explicit ChannelConfig(std::string address); - - std::string transport; - std::string key; - std::string address; - std::string portStr; - uint16_t port; -}; - -std::string toStage(RLM::REQUEST_TYPE type) -{ - switch (type) - { - case RLM::AUTHORIZE: return "authorize"; - case RLM::AUTHENTICATE: return "authenticate"; - case RLM::POST_AUTH: return "postauth"; - case RLM::PRE_ACCT: return "preacct"; - case RLM::ACCOUNT: return "accounting"; - } - return ""; -} - -enum Packet -{ - PING, - PONG, - DATA -}; - -std::map packetCodes; -std::map resultCodes; -std::map returnCodes; - -class PacketParser : public EnumParser -{ - public: - PacketParser(NodeParser* next, Packet& packet, std::string& packetStr) - : EnumParser(next, packet, packetStr, packetCodes) - { - if (!packetCodes.empty()) - return; - packetCodes["ping"] = PING; - packetCodes["pong"] = PONG; - packetCodes["data"] = DATA; - } -}; - -class ResultParser : public EnumParser -{ - public: - ResultParser(NodeParser* next, bool& result, std::string& resultStr) - : EnumParser(next, result, resultStr, resultCodes) - { - if (!resultCodes.empty()) - return; - resultCodes["no"] = false; - resultCodes["ok"] = true; - } -}; - -class ReturnCodeParser : public EnumParser -{ - public: - ReturnCodeParser(NodeParser* next, int& returnCode, std::string& returnCodeStr) - : EnumParser(next, returnCode, returnCodeStr, returnCodes) - { - if (!returnCodes.empty()) - return; - returnCodes["reject"] = STG_REJECT; - returnCodes["fail"] = STG_FAIL; - returnCodes["ok"] = STG_OK; - returnCodes["handled"] = STG_HANDLED; - returnCodes["invalid"] = STG_INVALID; - returnCodes["userlock"] = STG_USERLOCK; - returnCodes["notfound"] = STG_NOTFOUND; - returnCodes["noop"] = STG_NOOP; - returnCodes["updated"] = STG_UPDATED; - } -}; - -class TopParser : public NodeParser -{ - public: - typedef void (*Callback) (void* /*data*/); - TopParser(Callback callback, void* data) - : m_packet(PING), - m_result(false), - m_returnCode(STG_REJECT), - m_packetParser(this, m_packet, m_packetStr), - m_resultParser(this, m_result, m_resultStr), - m_returnCodeParser(this, m_returnCode, m_returnCodeStr), - m_replyParser(this, m_reply), - m_modifyParser(this, m_modify), - m_callback(callback), m_data(data) - {} - - virtual NodeParser* parseStartMap() { return this; } - virtual NodeParser* parseMapKey(const std::string& value) - { - std::string key = ToLower(value); - - if (key == "packet") - return &m_packetParser; - else if (key == "result") - return &m_resultParser; - else if (key == "reply") - return &m_replyParser; - else if (key == "modify") - return &m_modifyParser; - else if (key == "return_code") - return &m_returnCodeParser; - - return this; - } - virtual NodeParser* parseEndMap() { m_callback(m_data); return this; } - - const std::string& packetStr() const { return m_packetStr; } - Packet packet() const { return m_packet; } - const std::string& resultStr() const { return m_resultStr; } - bool result() const { return m_result; } - const std::string& returnCodeStr() const { return m_returnCodeStr; } - int returnCode() const { return m_returnCode; } - const PairsParser::Pairs& reply() const { return m_reply; } - const PairsParser::Pairs& modify() const { return m_modify; } - - private: - std::string m_packetStr; - Packet m_packet; - std::string m_resultStr; - bool m_result; - std::string m_returnCodeStr; - int m_returnCode; - PairsParser::Pairs m_reply; - PairsParser::Pairs m_modify; - - PacketParser m_packetParser; - ResultParser m_resultParser; - ReturnCodeParser m_returnCodeParser; - PairsParser m_replyParser; - PairsParser m_modifyParser; - - Callback m_callback; - void* m_data; -}; - -class ProtoParser : public Parser -{ - public: - ProtoParser(TopParser::Callback callback, void* data) - : Parser( &m_topParser ), - m_topParser(callback, data) - {} - - const std::string& packetStr() const { return m_topParser.packetStr(); } - Packet packet() const { return m_topParser.packet(); } - const std::string& resultStr() const { return m_topParser.resultStr(); } - bool result() const { return m_topParser.result(); } - const std::string& returnCodeStr() const { return m_topParser.returnCodeStr(); } - int returnCode() const { return m_topParser.returnCode(); } - const PairsParser::Pairs& reply() const { return m_topParser.reply(); } - const PairsParser::Pairs& modify() const { return m_topParser.modify(); } - - private: - TopParser m_topParser; -}; - -class PacketGen : public Gen -{ - public: - explicit PacketGen(const std::string& type) - : m_type(type) - { - m_gen.add("packet", m_type); - } - void run(yajl_gen_t* handle) const - { - m_gen.run(handle); - } - PacketGen& add(const std::string& key, const std::string& value) - { - m_gen.add(key, new StringGen(value)); - return *this; - } - PacketGen& add(const std::string& key, MapGen& map) - { - m_gen.add(key, map); - return *this; - } - private: - MapGen m_gen; - StringGen m_type; -}; - -} - -class Conn::Impl -{ -public: - Impl(const std::string& address, Callback callback, void* data); - ~Impl(); - - bool stop(); - bool connected() const { return m_connected; } - - bool request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs); - -private: - ChannelConfig m_config; - - int m_sock; - - bool m_running; - bool m_stopped; - - time_t m_lastPing; - time_t m_lastActivity; - - pthread_t m_thread; - pthread_mutex_t m_mutex; - - Callback m_callback; - void* m_data; - - ProtoParser m_parser; - - bool m_connected; - - void m_writeHeader(REQUEST_TYPE type, const std::string& userName, const std::string& password); - void m_writePairBlock(const PAIRS& source); - PAIRS m_readPairBlock(); - - static void* run(void* ); - - void runImpl(); - - bool start(); - - int connect(); - int connectTCP(); - int connectUNIX(); - - bool read(); - bool tick(); - - static void process(void* data); - void processPing(); - void processPong(); - void processData(); - bool sendPing(); - bool sendPong(); - - static bool write(void* data, const char* buf, size_t size); -}; - -ChannelConfig::ChannelConfig(std::string addr) -{ - // unix:pass@/var/run/stg.sock - // tcp:secret@192.168.0.1:12345 - // udp:key@isp.com.ua:54321 - - size_t pos = addr.find_first_of(':'); - if (pos == std::string::npos) - throw Error("Missing transport name."); - transport = ToLower(addr.substr(0, pos)); - addr = addr.substr(pos + 1); - if (addr.empty()) - throw Error("Missing address to connect to."); - pos = addr.find_first_of('@'); - if (pos != std::string::npos) { - key = addr.substr(0, pos); - addr = addr.substr(pos + 1); - if (addr.empty()) - throw Error("Missing address to connect to."); - } - if (transport == "unix") - { - address = addr; - return; - } - pos = addr.find_first_of(':'); - if (pos == std::string::npos) - throw Error("Missing port."); - address = addr.substr(0, pos); - portStr = addr.substr(pos + 1); - if (str2x(portStr, port)) - throw Error("Invalid port value."); -} - -Conn::Conn(const std::string& address, Callback callback, void* data) - : m_impl(new Impl(address, callback, data)) -{ -} - -Conn::~Conn() -{ -} - -bool Conn::stop() -{ - return m_impl->stop(); -} - -bool Conn::connected() const -{ - return m_impl->connected(); -} - -bool Conn::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) -{ - return m_impl->request(type, userName, password, pairs); -} - -Conn::Impl::Impl(const std::string& address, Callback callback, void* data) - : m_config(address), - m_sock(connect()), - m_running(false), - m_stopped(true), - m_lastPing(time(NULL)), - m_lastActivity(m_lastPing), - m_callback(callback), - m_data(data), - m_parser(&Conn::Impl::process, this), - m_connected(true) -{ - pthread_mutex_init(&m_mutex, NULL); -} - -Conn::Impl::~Impl() -{ - stop(); - shutdown(m_sock, SHUT_RDWR); - close(m_sock); - pthread_mutex_destroy(&m_mutex); -} - -bool Conn::Impl::stop() -{ - m_connected = false; - - if (m_stopped) - return true; - - m_running = false; - - for (size_t i = 0; i < 25 && !m_stopped; i++) { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - - if (m_stopped) { - pthread_join(m_thread, NULL); - return true; - } - - return false; -} - -bool Conn::Impl::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) -{ - if (!m_running) - if (!start()) - return false; - MapGen map; - for (PAIRS::const_iterator it = pairs.begin(); it != pairs.end(); ++it) - map.add(it->first, new StringGen(it->second)); - map.add("Radius-Username", new StringGen(userName)); - map.add("Radius-Userpass", new StringGen(password)); - - PacketGen gen("data"); - gen.add("stage", toStage(type)) - .add("pairs", map); - - STG_LOCKER lock(m_mutex); - - m_lastPing = time(NULL); - - return generate(gen, &Conn::Impl::write, this); -} - -void Conn::Impl::runImpl() -{ - m_running = true; - - while (m_running) { - fd_set fds; - - FD_ZERO(&fds); - FD_SET(m_sock, &fds); - - struct timeval tv; - tv.tv_sec = 0; - tv.tv_usec = 500000; - - int res = select(m_sock + 1, &fds, NULL, NULL, &tv); - if (res < 0) - { - if (errno == EINTR) - continue; - RadLog("'select' is failed: %s", strerror(errno)); - break; - } - - - if (!m_running) - break; - - STG_LOCKER lock(m_mutex); - - if (res > 0) - { - if (FD_ISSET(m_sock, &fds)) - m_running = read(); - } - else - m_running = tick(); - } - - m_connected = false; - m_stopped = true; -} - -bool Conn::Impl::start() -{ - int res = pthread_create(&m_thread, NULL, &Conn::Impl::run, this); - if (res != 0) - return false; - return true; -} - -int Conn::Impl::connect() -{ - if (m_config.transport == "tcp") - return connectTCP(); - else if (m_config.transport == "unix") - return connectUNIX(); - throw Error("Invalid transport type: '" + m_config.transport + "'. Should be 'tcp' or 'unix'."); -} - -int Conn::Impl::connectTCP() -{ - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - - hints.ai_family = AF_INET; /* Allow IPv4 */ - hints.ai_socktype = SOCK_STREAM; /* Stream socket */ - hints.ai_flags = 0; /* For wildcard IP address */ - hints.ai_protocol = 0; /* Any protocol */ - hints.ai_canonname = NULL; - hints.ai_addr = NULL; - hints.ai_next = NULL; - - addrinfo* ais = NULL; - int res = getaddrinfo(m_config.address.c_str(), m_config.portStr.c_str(), &hints, &ais); - if (res != 0) - throw Error("Error resolvin address '" + m_config.address + "': " + gai_strerror(res)); - - for (addrinfo* ai = ais; ai != NULL; ai = ai->ai_next) - { - int fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd == -1) - { - Error error(std::string("Error creating TCP socket: ") + strerror(errno)); - freeaddrinfo(ais); - throw error; - } - if (::connect(fd, ai->ai_addr, ai->ai_addrlen) == -1) - { - shutdown(fd, SHUT_RDWR); - close(fd); - RadLog("'connect' is failed: %s", strerror(errno)); - continue; - } - freeaddrinfo(ais); - return fd; - } - - freeaddrinfo(ais); - - throw Error("Failed to resolve '" + m_config.address); -}; - -int Conn::Impl::connectUNIX() -{ - int fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd == -1) - throw Error(std::string("Error creating UNIX socket: ") + strerror(errno)); - struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, m_config.address.c_str(), m_config.address.length()); - if (::connect(fd, reinterpret_cast(&addr), sizeof(addr)) == -1) - { - Error error(std::string("Error connecting UNIX socket: ") + strerror(errno)); - shutdown(fd, SHUT_RDWR); - close(fd); - throw error; - } - return fd; -} - -bool Conn::Impl::read() -{ - static std::vector buffer(1024); - ssize_t res = ::read(m_sock, buffer.data(), buffer.size()); - if (res < 0) - { - RadLog("Failed to read data: %s", strerror(errno)); - return false; - } - m_lastActivity = time(NULL); - RadLog("Read %d bytes.\n%s\n", res, std::string(buffer.data(), res).c_str()); - if (res == 0) - { - m_parser.last(); - return false; - } - return m_parser.append(buffer.data(), res); -} - -bool Conn::Impl::tick() -{ - time_t now = time(NULL); - if (difftime(now, m_lastActivity) > CONN_TIMEOUT) - { - int delta = difftime(now, m_lastActivity); - RadLog("Connection timeout: %d sec.", delta); - //m_logger("Connection to " + m_remote + " timed out."); - return false; - } - if (difftime(now, m_lastPing) > PING_TIMEOUT) - { - int delta = difftime(now, m_lastPing); - RadLog("Ping timeout: %d sec. Sending ping...", delta); - sendPing(); - } - return true; -} - -void Conn::Impl::process(void* data) -{ - Impl& impl = *static_cast(data); - switch (impl.m_parser.packet()) - { - case PING: - impl.processPing(); - return; - case PONG: - impl.processPong(); - return; - case DATA: - impl.processData(); - return; - } - RadLog("Received invalid packet type: '%s'.", impl.m_parser.packetStr().c_str()); -} - -void Conn::Impl::processPing() -{ - sendPong(); -} - -void Conn::Impl::processPong() -{ - m_lastActivity = time(NULL); -} - -void Conn::Impl::processData() -{ - RESULT data; - if (m_parser.result()) - { - for (PairsParser::Pairs::const_iterator it = m_parser.reply().begin(); it != m_parser.reply().end(); ++it) - data.reply.push_back(std::make_pair(it->first, it->second)); - for (PairsParser::Pairs::const_iterator it = m_parser.modify().begin(); it != m_parser.modify().end(); ++it) - data.modify.push_back(std::make_pair(it->first, it->second)); - data.returnCode = STG_UPDATED; - } - else - data.returnCode = m_parser.returnCode(); - m_callback(m_data, data); -} - -bool Conn::Impl::sendPing() -{ - PacketGen gen("ping"); - - m_lastPing = time(NULL); - - return generate(gen, &Conn::Impl::write, this); -} - -bool Conn::Impl::sendPong() -{ - PacketGen gen("pong"); - - m_lastPing = time(NULL); - - return generate(gen, &Conn::Impl::write, this); -} - -bool Conn::Impl::write(void* data, const char* buf, size_t size) -{ - std::string json(buf, size); - RadLog("Sending JSON: %s", json.c_str()); - Conn::Impl& impl = *static_cast(data); - while (size > 0) - { - ssize_t res = ::send(impl.m_sock, buf, size, MSG_NOSIGNAL); - if (res < 0) - { - impl.m_connected = false; - RadLog("Failed to write data: %s.", strerror(errno)); - return false; - } - size -= res; - } - return true; -} - -void* Conn::Impl::run(void* data) -{ - Impl& impl = *static_cast(data); - impl.runImpl(); - return NULL; -} diff --git a/projects/rlm_stg/conn.h b/projects/rlm_stg/conn.h deleted file mode 100644 index 6233b154..00000000 --- a/projects/rlm_stg/conn.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef __STG_RLM_CONN_H__ -#define __STG_RLM_CONN_H__ - -#include "types.h" - -#include "stg/os_int.h" - -#include - -#include -#include - -namespace STG -{ -namespace RLM -{ - -class Conn -{ - public: - struct Error : std::runtime_error { - explicit Error(const std::string& message) : runtime_error(message) {} - }; - - typedef bool (*Callback)(void* /*data*/, const RESULT& /*result*/); - - Conn(const std::string& address, Callback callback, void* data); - ~Conn(); - - bool stop(); - bool connected() const; - - bool request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs); - - private: - class Impl; - boost::scoped_ptr m_impl; -}; - -} -} - -#endif diff --git a/projects/rlm_stg/iface.cpp b/projects/rlm_stg/iface.cpp deleted file mode 100644 index f97593f4..00000000 --- a/projects/rlm_stg/iface.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "iface.h" - -#include "stg_client.h" -#include "types.h" -#include "radlog.h" - -#include -#include - -#include - -namespace RLM = STG::RLM; - -using RLM::Client; -using RLM::PAIRS; -using RLM::RESULT; -using RLM::REQUEST_TYPE; - -namespace -{ - -STG_PAIR* toSTGPairs(const PAIRS& source) -{ - STG_PAIR * pairs = new STG_PAIR[source.size() + 1]; - for (size_t pos = 0; pos < source.size(); ++pos) { - bzero(pairs[pos].key, sizeof(pairs[pos].key)); - bzero(pairs[pos].value, sizeof(pairs[pos].value)); - strncpy(pairs[pos].key, source[pos].first.c_str(), sizeof(pairs[pos].key)); - strncpy(pairs[pos].value, source[pos].second.c_str(), sizeof(pairs[pos].value)); - } - bzero(pairs[source.size()].key, sizeof(pairs[source.size()].key)); - bzero(pairs[source.size()].value, sizeof(pairs[source.size()].value)); - - return pairs; -} - -PAIRS fromSTGPairs(const STG_PAIR* pairs) -{ - const STG_PAIR* pair = pairs; - PAIRS res; - - while (!emptyPair(pair)) { - res.push_back(std::pair(pair->key, pair->value)); - ++pair; - } - - return res; -} - -STG_RESULT toResult(const RESULT& source) -{ - STG_RESULT result; - result.modify = toSTGPairs(source.modify); - result.reply = toSTGPairs(source.reply); - result.returnCode = source.returnCode; - return result; -} - -STG_RESULT emptyResult() -{ - STG_RESULT result = {NULL, NULL, STG_REJECT}; - return result; -} - -std::string toString(const char* value) -{ - if (value == NULL) - return ""; - else - return value; -} - -STG_RESULT stgRequest(REQUEST_TYPE type, const char* userName, const char* password, const STG_PAIR* pairs) -{ - Client* client = Client::get(); - if (client == NULL) { - RadLog("Client is not configured."); - return emptyResult(); - } - try { - return toResult(client->request(type, toString(userName), toString(password), fromSTGPairs(pairs))); - } catch (const std::runtime_error& ex) { - RadLog("Error: '%s'.", ex.what()); - return emptyResult(); - } -} - -} - -int stgInstantiateImpl(const char* address) -{ - if (Client::configure(toString(address))) - return 1; - - return 0; -} - -STG_RESULT stgAuthorizeImpl(const char* userName, const char* password, const STG_PAIR* pairs) -{ - return stgRequest(RLM::AUTHORIZE, userName, password, pairs); -} - -STG_RESULT stgAuthenticateImpl(const char* userName, const char* password, const STG_PAIR* pairs) -{ - return stgRequest(RLM::AUTHENTICATE, userName, password, pairs); -} - -STG_RESULT stgPostAuthImpl(const char* userName, const char* password, const STG_PAIR* pairs) -{ - return stgRequest(RLM::POST_AUTH, userName, password, pairs); -} - -STG_RESULT stgPreAcctImpl(const char* userName, const char* password, const STG_PAIR* pairs) -{ - return stgRequest(RLM::PRE_ACCT, userName, password, pairs); -} - -STG_RESULT stgAccountingImpl(const char* userName, const char* password, const STG_PAIR* pairs) -{ - return stgRequest(RLM::ACCOUNT, userName, password, pairs); -} diff --git a/projects/rlm_stg/iface.h b/projects/rlm_stg/iface.h deleted file mode 100644 index e863e939..00000000 --- a/projects/rlm_stg/iface.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __STG_IFACE_H__ -#define __STG_IFACE_H__ - -#include - -#include "stgpair.h" - -#ifdef __cplusplus -extern "C" { -#endif - -int stgInstantiateImpl(const char* address); -STG_RESULT stgAuthorizeImpl(const char* userName, const char* password, const STG_PAIR* vps); -STG_RESULT stgAuthenticateImpl(const char* userName, const char* password, const STG_PAIR* vps); -STG_RESULT stgPostAuthImpl(const char* userName, const char* password, const STG_PAIR* vps); -STG_RESULT stgPreAcctImpl(const char* userName, const char* password, const STG_PAIR* vps); -STG_RESULT stgAccountingImpl(const char* userName, const char* password, const STG_PAIR* vps); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/projects/rlm_stg/radlog.c b/projects/rlm_stg/radlog.c deleted file mode 100644 index 523dc1c4..00000000 --- a/projects/rlm_stg/radlog.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "radlog.h" - -//#ifndef NDEBUG -//#define NDEBUG -#include -#include -#include -//#undef NDEBUG -//#endif - -#include - -void RadLog(const char* format, ...) -{ - char buf[1024]; - - va_list vl; - va_start(vl, format); - vsnprintf(buf, sizeof(buf), format, vl); - va_end(vl); - - DEBUG("[rlm_stg] *** %s", buf); -} diff --git a/projects/rlm_stg/radlog.h b/projects/rlm_stg/radlog.h deleted file mode 100644 index 00a5dcb5..00000000 --- a/projects/rlm_stg/radlog.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __STG_RADLOG_H__ -#define __STG_RADLOG_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -void RadLog(const char* format, ...); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/projects/rlm_stg/rlm_stg.c b/projects/rlm_stg/rlm_stg.c deleted file mode 100644 index 84df4e7b..00000000 --- a/projects/rlm_stg/rlm_stg.c +++ /dev/null @@ -1,420 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -/* - * FreeRADIUS module for data access via Stargazer - * - * $Revision: 1.8 $ - * $Date: 2010/08/14 04:15:08 $ - * - */ - -#include "iface.h" -#include "stgpair.h" - -#include -#include -#include - -#include // size_t - -typedef struct rlm_stg_t { - char* address; -} rlm_stg_t; - -static const CONF_PARSER module_config[] = { - { "address", PW_TYPE_STRING_PTR, offsetof(rlm_stg_t, address), NULL, "unix:/var/run/stg.sock"}, - - { NULL, -1, 0, NULL, NULL } /* end the list */ -}; - -static void deletePairs(STG_PAIR* pairs) -{ - free(pairs); -} - -static size_t toVPS(const STG_PAIR* pairs, VALUE_PAIR** vps) -{ - const STG_PAIR* pair = pairs; - size_t count = 0; - - while (!emptyPair(pair)) { - VALUE_PAIR* vp = pairmake(pair->key, pair->value, T_OP_SET); - if (vp != NULL) { - pairadd(vps, vp); - ++count; - } - ++pair; - } - - return count; -} - -static size_t toReply(STG_RESULT result, REQUEST* request) -{ - size_t count = 0; - - count += toVPS(result.modify, &request->config_items); - pairfree(&request->reply->vps); - count += toVPS(result.reply, &request->reply->vps); - - deletePairs(result.modify); - deletePairs(result.reply); - - return count; -} - -static int countVPS(const VALUE_PAIR* pairs) -{ - unsigned count = 0; - while (pairs != NULL) { - ++count; - pairs = pairs->next; - } - return count; -} - -static STG_PAIR* fromVPS(const VALUE_PAIR* pairs) -{ - unsigned size = countVPS(pairs); - STG_PAIR* res = (STG_PAIR*)malloc(sizeof(STG_PAIR) * (size + 1)); - size_t pos = 0; - while (pairs != NULL) { - bzero(res[pos].key, sizeof(res[0].key)); - bzero(res[pos].value, sizeof(res[0].value)); - strncpy(res[pos].key, pairs->name, sizeof(res[0].key)); - vp_prints_value(res[pos].value, sizeof(res[0].value), (VALUE_PAIR*)pairs, 0); - ++pos; - pairs = pairs->next; - } - bzero(res[pos].key, sizeof(res[0].key)); - bzero(res[pos].value, sizeof(res[0].value)); - return res; -} - -static int toRLMCode(int code) -{ - switch (code) - { - case STG_REJECT: return RLM_MODULE_REJECT; - case STG_FAIL: return RLM_MODULE_FAIL; - case STG_OK: return RLM_MODULE_OK; - case STG_HANDLED: return RLM_MODULE_HANDLED; - case STG_INVALID: return RLM_MODULE_INVALID; - case STG_USERLOCK: return RLM_MODULE_USERLOCK; - case STG_NOTFOUND: return RLM_MODULE_NOTFOUND; - case STG_NOOP: return RLM_MODULE_NOOP; - case STG_UPDATED: return RLM_MODULE_UPDATED; - } - return RLM_MODULE_REJECT; -} - -/* - * Do any per-module initialization that is separate to each - * configured instance of the module. e.g. set up connections - * to external databases, read configuration files, set up - * dictionary entries, etc. - * - * If configuration information is given in the config section - * that must be referenced in later calls, store a handle to it - * in *instance otherwise put a null pointer there. - */ -static int stg_instantiate(CONF_SECTION* conf, void** instance) -{ - rlm_stg_t* data; - - /* - * Set up a storage area for instance data - */ - data = rad_malloc(sizeof(*data)); - if (!data) - return -1; - - memset(data, 0, sizeof(*data)); - - /* - * If the configuration parameters can't be parsed, then - * fail. - */ - if (cf_section_parse(conf, data, module_config) < 0) { - free(data); - return -1; - } - - if (!stgInstantiateImpl(data->address)) { - free(data); - return -1; - } - - *instance = data; - - return 0; -} - -/* - * Find the named user in this modules database. Create the set - * of attribute-value pairs to check and reply with for this user - * from the database. The authentication code only needs to check - * the password, the rest is done here. - */ -static int stg_authorize(void* instance, REQUEST* request) -{ - STG_RESULT result; - STG_PAIR* pairs = fromVPS(request->packet->vps); - size_t count = 0; - const char* username = NULL; - const char* password = NULL; - - instance = instance; - - DEBUG("rlm_stg: stg_authorize()"); - - if (request->username) { - username = request->username->data.strvalue; - DEBUG("rlm_stg: stg_authorize() request username field: '%s'", username); - } - - if (request->password) { - password = request->password->data.strvalue; - DEBUG("rlm_stg: stg_authorize() request password field: '%s'", password); - } - - result = stgAuthorizeImpl(username, password, pairs); - deletePairs(pairs); - - if (!result.modify && !result.reply) { - DEBUG("rlm_stg: stg_authorize() failed."); - return RLM_MODULE_REJECT; - } - - count = toReply(result, request); - - if (count) - return RLM_MODULE_UPDATED; - - return toRLMCode(result.returnCode); -} - -/* - * Authenticate the user with the given password. - */ -static int stg_authenticate(void* instance, REQUEST* request) -{ - STG_RESULT result; - STG_PAIR* pairs = fromVPS(request->packet->vps); - size_t count = 0; - const char* username = NULL; - const char* password = NULL; - - instance = instance; - - DEBUG("rlm_stg: stg_authenticate()"); - - if (request->username) { - username = request->username->data.strvalue; - DEBUG("rlm_stg: stg_authenticate() request username field: '%s'", username); - } - - if (request->password) { - password = request->password->data.strvalue; - DEBUG("rlm_stg: stg_authenticate() request password field: '%s'", password); - } - - result = stgAuthenticateImpl(username, password, pairs); - deletePairs(pairs); - - if (!result.modify && !result.reply) { - DEBUG("rlm_stg: stg_authenticate() failed."); - return RLM_MODULE_REJECT; - } - - count = toReply(result, request); - - if (count) - return RLM_MODULE_UPDATED; - - return toRLMCode(result.returnCode); -} - -/* - * Massage the request before recording it or proxying it - */ -static int stg_preacct(void* instance, REQUEST* request) -{ - STG_RESULT result; - STG_PAIR* pairs = fromVPS(request->packet->vps); - size_t count = 0; - const char* username = NULL; - const char* password = NULL; - - DEBUG("rlm_stg: stg_preacct()"); - - instance = instance; - - if (request->username) { - username = request->username->data.strvalue; - DEBUG("rlm_stg: stg_preacct() request username field: '%s'", username); - } - - if (request->password) { - password = request->password->data.strvalue; - DEBUG("rlm_stg: stg_preacct() request password field: '%s'", password); - } - - result = stgPreAcctImpl(username, password, pairs); - deletePairs(pairs); - - if (!result.modify && !result.reply) { - DEBUG("rlm_stg: stg_preacct() failed."); - return RLM_MODULE_REJECT; - } - - count = toReply(result, request); - - if (count) - return RLM_MODULE_UPDATED; - - return toRLMCode(result.returnCode); -} - -/* - * Write accounting information to this modules database. - */ -static int stg_accounting(void* instance, REQUEST* request) -{ - STG_RESULT result; - STG_PAIR* pairs = fromVPS(request->packet->vps); - size_t count = 0; - const char* username = NULL; - const char* password = NULL; - - DEBUG("rlm_stg: stg_accounting()"); - - instance = instance; - - if (request->username) { - username = request->username->data.strvalue; - DEBUG("rlm_stg: stg_accounting() request username field: '%s'", username); - } - - if (request->password) { - password = request->password->data.strvalue; - DEBUG("rlm_stg: stg_accounting() request password field: '%s'", password); - } - - result = stgAccountingImpl(username, password, pairs); - deletePairs(pairs); - - if (!result.modify && !result.reply) { - DEBUG("rlm_stg: stg_accounting() failed."); - return RLM_MODULE_REJECT; - } - - count = toReply(result, request); - - if (count) - return RLM_MODULE_UPDATED; - - return toRLMCode(result.returnCode); -} - -/* - * See if a user is already logged in. Sets request->simul_count to the - * current session count for this user and sets request->simul_mpp to 2 - * if it looks like a multilink attempt based on the requested IP - * address, otherwise leaves request->simul_mpp alone. - * - * Check twice. If on the first pass the user exceeds his - * max. number of logins, do a second pass and validate all - * logins by querying the terminal server (using eg. SNMP). - */ -static int stg_checksimul(void* instance, REQUEST* request) -{ - DEBUG("rlm_stg: stg_checksimul()"); - - instance = instance; - - request->simul_count = 0; - - return RLM_MODULE_OK; -} - -static int stg_postauth(void* instance, REQUEST* request) -{ - STG_RESULT result; - STG_PAIR* pairs = fromVPS(request->packet->vps); - size_t count = 0; - const char* username = NULL; - const char* password = NULL; - - DEBUG("rlm_stg: stg_postauth()"); - - instance = instance; - - if (request->username) { - username = request->username->data.strvalue; - DEBUG("rlm_stg: stg_postauth() request username field: '%s'", username); - } - - if (request->password) { - password = request->password->data.strvalue; - DEBUG("rlm_stg: stg_postauth() request password field: '%s'", password); - } - - result = stgPostAuthImpl(username, password, pairs); - deletePairs(pairs); - - if (!result.modify && !result.reply) { - DEBUG("rlm_stg: stg_postauth() failed."); - return RLM_MODULE_REJECT; - } - - count = toReply(result, request); - - if (count) - return RLM_MODULE_UPDATED; - - return toRLMCode(result.returnCode); -} - -static int stg_detach(void* instance) -{ - free(((struct rlm_stg_t*)instance)->address); - free(instance); - return 0; -} - -module_t rlm_stg = { - RLM_MODULE_INIT, - "stg", - RLM_TYPE_THREAD_UNSAFE, /* type */ - stg_instantiate, /* instantiation */ - stg_detach, /* detach */ - { - stg_authenticate, /* authentication */ - stg_authorize, /* authorization */ - stg_preacct, /* preaccounting */ - stg_accounting, /* accounting */ - stg_checksimul, /* checksimul */ - NULL, /* pre-proxy */ - NULL, /* post-proxy */ - stg_postauth /* post-auth */ - }, -}; diff --git a/projects/rlm_stg/stg_client.cpp b/projects/rlm_stg/stg_client.cpp deleted file mode 100644 index e34c50cd..00000000 --- a/projects/rlm_stg/stg_client.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#include "stg_client.h" - -#include "conn.h" -#include "radlog.h" - -#include "stg/locker.h" -#include "stg/common.h" - -#include -#include - -using STG::RLM::Client; -using STG::RLM::Conn; -using STG::RLM::RESULT; - -namespace { - -Client* stgClient = NULL; - -} - -class Client::Impl -{ - public: - explicit Impl(const std::string& address); - ~Impl(); - - bool stop() { return m_conn ? m_conn->stop() : true; } - - RESULT request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs); - - private: - std::string m_address; - boost::scoped_ptr m_conn; - - pthread_mutex_t m_mutex; - pthread_cond_t m_cond; - bool m_done; - RESULT m_result; - - static bool callback(void* data, const RESULT& result) - { - Impl& impl = *static_cast(data); - STG_LOCKER lock(impl.m_mutex); - impl.m_result = result; - impl.m_done = true; - pthread_cond_signal(&impl.m_cond); - return true; - } -}; - -Client::Impl::Impl(const std::string& address) - : m_address(address) -{ - try - { - m_conn.reset(new Conn(m_address, &Impl::callback, this)); - } - catch (const std::runtime_error& ex) - { - RadLog("Connection error: %s.", ex.what()); - } - pthread_mutex_init(&m_mutex, NULL); - pthread_cond_init(&m_cond, NULL); - m_done = false; -} - -Client::Impl::~Impl() -{ - pthread_cond_destroy(&m_cond); - pthread_mutex_destroy(&m_mutex); -} - -RESULT Client::Impl::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) -{ - STG_LOCKER lock(m_mutex); - if (!m_conn || !m_conn->connected()) - m_conn.reset(new Conn(m_address, &Impl::callback, this)); - if (!m_conn->connected()) - throw Conn::Error("Failed to create connection to '" + m_address + "'."); - - m_done = false; - m_conn->request(type, userName, password, pairs); - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += 5; - int res = 0; - while (!m_done && res == 0) - res = pthread_cond_timedwait(&m_cond, &m_mutex, &ts); - if (res != 0) - throw Conn::Error("Request failed."); - return m_result; -} - -Client::Client(const std::string& address) - : m_impl(new Impl(address)) -{ -} - -Client::~Client() -{ -} - -bool Client::stop() -{ - return m_impl->stop(); -} - -RESULT Client::request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs) -{ - return m_impl->request(type, userName, password, pairs); -} - -Client* Client::get() -{ - return stgClient; -} - -bool Client::configure(const std::string& address) -{ - if ( stgClient != NULL ) - return stgClient->configure(address); - try { - stgClient = new Client(address); - return true; - } catch (const std::exception& ex) { - RadLog("Client configuration error: %s.", ex.what()); - } - return false; -} diff --git a/projects/rlm_stg/stg_client.h b/projects/rlm_stg/stg_client.h deleted file mode 100644 index 917d0e51..00000000 --- a/projects/rlm_stg/stg_client.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef __STG_RLM_CLIENT_H__ -#define __STG_RLM_CLIENT_H__ - -#include "types.h" - -#include "stg/os_int.h" - -#include - -#include - -namespace STG -{ -namespace RLM -{ - -class Client -{ -public: - explicit Client(const std::string& address); - ~Client(); - - bool stop(); - - static Client* get(); - static bool configure(const std::string& address); - - RESULT request(REQUEST_TYPE type, const std::string& userName, const std::string& password, const PAIRS& pairs); - -private: - class Impl; - boost::scoped_ptr m_impl; -}; - -} // namespace RLM -} // namespace STG - -#endif diff --git a/projects/rlm_stg/stgpair.h b/projects/rlm_stg/stgpair.h deleted file mode 100644 index ef7ab4b7..00000000 --- a/projects/rlm_stg/stgpair.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __STG_STGPAIR_H__ -#define __STG_STGPAIR_H__ - -#include - -#define STGPAIR_KEYLENGTH 64 -#define STGPAIR_VALUELENGTH 256 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct STG_PAIR { - char key[STGPAIR_KEYLENGTH]; - char value[STGPAIR_VALUELENGTH]; -} STG_PAIR; - -typedef struct STG_RESULT { - STG_PAIR* modify; - STG_PAIR* reply; - int returnCode; -} STG_RESULT; - -inline -int emptyPair(const STG_PAIR* pair) -{ - return pair == NULL || pair->key[0] == '\0' || pair->value[0] == '\0'; -} - -enum -{ - STG_REJECT, - STG_FAIL, - STG_OK, - STG_HANDLED, - STG_INVALID, - STG_USERLOCK, - STG_NOTFOUND, - STG_NOOP, - STG_UPDATED -}; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/projects/rlm_stg/types.h b/projects/rlm_stg/types.h deleted file mode 100644 index 2bc721fc..00000000 --- a/projects/rlm_stg/types.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef __STG_RLM_CLIENT_CONN_H__ -#define __STG_RLM_CLIENT_CONN_H__ - -#include -#include - -namespace STG -{ -namespace RLM -{ - -typedef std::vector > PAIRS; - -struct RESULT -{ - PAIRS modify; - PAIRS reply; - int returnCode; -}; - -enum REQUEST_TYPE { - AUTHORIZE, - AUTHENTICATE, - POST_AUTH, - PRE_ACCT, - ACCOUNT -}; - -} // namespace RLM -} // namespace STG - -#endif diff --git a/projects/rscriptd/Makefile b/projects/rscriptd/Makefile deleted file mode 100644 index 98b2f5e4..00000000 --- a/projects/rscriptd/Makefile +++ /dev/null @@ -1,115 +0,0 @@ -############################################################################### -# $Id: Makefile,v 1.18 2010/02/11 12:22:01 faust Exp $ -############################################################################### - -include ../../Makefile.conf - -PROG = rscriptd - -SRCS = ./main.cpp \ - ./listener.cpp \ - ./pidfile.cpp - -STGLIBS = scriptexecuter \ - conffiles \ - logger \ - crypto \ - common - -STGLIBS_INCS = $(addprefix -I ../../stglibs/,$(addsuffix .lib/include,$(STGLIBS))) -STGLIBS_LIBS = $(addprefix -L ../../stglibs/,$(addsuffix .lib,$(STGLIBS))) - -LIBS += $(addprefix -lstg,$(STGLIBS)) $(LIB_THREAD) $(LIBICONV) - -SEARCH_DIRS = -I ../../include - -OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))) - -CXXFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -CFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) - -ifneq ($(OS),darwin) -LDFLAGS += -Wl,-E -endif - -LDFLAGS += $(STGLIBS_LIBS) - -.PHONY: all clean distclean libs install uninstall -all: libs $(PROG) ../../Makefile.conf - -libs: - $(MAKE) -C $(DIR_LIBSRC) - -$(PROG): $(OBJS) - $(CXX) $^ $(LDFLAGS) $(LIBS) -o $(PROG) - -clean: - rm -f deps $(PROG) *.o tags *.*~ .OS - rm -f .OS - rm -f .store - rm -f .db.sql - rm -f core* - $(MAKE) -C $(DIR_LIBSRC) clean - -distclean: clean - rm -f ../../Makefile.conf - -install: install-bin install-data - -install-bin: -ifeq ($(DEBUG), yes) - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/sbin - install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/sbin/$(PROG) -else - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/sbin - install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG) -endif - $(MAKE) -C $(DIR_LIBSRC) install - -install-data: - # Install etc - mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/rscriptd - install -m $(DATA_MODE) -o $(OWNER) ./rscriptd.conf $(PREFIX)/etc/rscriptd/rscriptd.conf -ifeq ($(OS), linux) - mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/rscriptd - install -m $(BIN_MODE) -o $(OWNER) ../stargazer/inst/linux/etc/stargazer/OnConnect $(PREFIX)/etc/rscriptd/ - install -m $(BIN_MODE) -o $(OWNER) ../stargazer/inst/linux/etc/stargazer/OnDisconnect $(PREFIX)/etc/rscriptd/ -else - mkdir -m $(DIR_MODE) -p $(PREFIX)/etc/rscriptd - install -m $(BIN_MODE) -o $(OWNER) ../stargazer/inst/freebsd/etc/stargazer/OnConnect $(PREFIX)/etc/rscriptd/ - install -m $(BIN_MODE) -o $(OWNER) ../stargazer/inst/freebsd/etc/stargazer/OnDisconnect $(PREFIX)/etc/rscriptd/ -endif - -uninstall: uninstall-bin uninstall-data - -uninstall-bin: - rm -f $(PREFIX)/usr/sbin/$(PROG) - -uninstall-data: - # Uninstall etc - rm -f $(PREFIX)/etc/rscriptd/rscriptd.conf - rm -f $(PREFIX)/etc/rscriptd/OnConnect - rm -f $(PREFIX)/etc/rscriptd/OnDisconnect - -ifneq ($(MAKECMDGOALS),distclean) -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),uninstall) --include deps -endif -endif -endif - -deps: $(SRCS) ../../Makefile.conf - $(MAKE) -C $(DIR_LIBSRC) - @>deps ;\ - for file in $(SRCS); do\ - echo "$$file" | grep ".c$$" > /dev/null;\ - if [ $$? -eq 0 ];\ - then\ - echo "`$(CC) $(CFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CC) $(CFLAGS) -c $$<' >> deps ;\ - else\ - echo "`$(CXX) $(CXXFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CXX) $(CXXFLAGS) -c $$<' >> deps ;\ - fi;\ - done diff --git a/projects/rscriptd/build b/projects/rscriptd/build deleted file mode 100755 index 995a9373..00000000 --- a/projects/rscriptd/build +++ /dev/null @@ -1,206 +0,0 @@ -#!/bin/sh - -# $Author: faust $ -# $Revision: 1.21 $ -# $Date: 2010/04/14 08:58:52 $ -###################################################### - -OS=unknown -sys=`uname -s` -release=`uname -r` -major=`printf "%s" "$release" | cut -d. -f1` -BUILD_DIR=`pwd` -CONFFILE="../../Makefile.conf" -PREFIX="/" -BIN_MODE=0755 -DATA_MODE=0644 -DIR_MODE=0755 -OWNER=root - -if [ "$1" = "debug" ] -then - DEFS="$DEFS -DDEBUG" - MAKEOPTS="$MAKEOPTS -j1" - CFLAGS="$CFLAGS -ggdb3 -W -Wall -Wextra" - CXXFLAGS="$CXXFLAGS -ggdb3 -W -Wall -Wextra" - DEBUG="yes" -else - DEFS="$DEFS -DNDEBUG" - DEBUG="no" -fi - -CFLAGS="$CFLAGS -I/usr/local/include" -CXXFLAGS="$CXXFLAGS -I/usr/local/include" -LDFLAGS="$LDFLAGS -L/usr/local/lib" - -if [ "$sys" = "Linux" ] -then - OS=linux - MAKE="make" -fi - -if [ "$sys" = "FreeBSD" ] -then - case $major in - 4) OS=bsd;; - 5) OS=bsd5;; - 6) OS=bsd5;; - 7) OS=bsd7;; - *) OS=bsd7;; - esac - MAKE="gmake" -fi - -if [ "$sys" = "Darwin" ] -then - OS=darwin - ETC_DIR="./inst/freebsd/etc/stargazer" - MAKE="gmake" -fi - -if [ "$OS" = "unknown" ] -then - printf "#############################################################################\n" - printf "# Sorry, but rscriptd is currently supported by Linux, FreeBSD and Darwin. #\n" - printf "#############################################################################\n" - exit 1 -fi - -printf "#############################################################################\n" -printf " Building rscriptd for $sys $release\n" -printf "#############################################################################\n" - -STG_LIBS="logger.lib - crypto.lib - common.lib - scriptexecuter.lib - conffiles.lib" - -if [ "$OS" = "linux" ] -then - DEFS="$DEFS -DLINUX" - LIB_THREAD=-lpthread -else - LIBICONV="-liconv" - if [ "$OS" = "bsd" ] - then - DEFS="$DEFS -DFREE_BSD" - else - if [ "$OS" = "bsd7" ] - then - DEFS="$DEFS -DFREE_BSD5" - LIB_THREAD=-lpthread - else - if [ "$OS" == "darwin" ] - then - DEFS="$DEFS -DDARWIN" - LIB_THREAD=-lpthread - else - LIB_THREAD=-lc_r - fi - fi - fi -fi - -if [ -z "$CC" ] -then - CC=gcc -fi - -if [ -z "$CXX" ] -then - CXX=g++ -fi - -printf "Checking CC... " -$CC --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CC not found\n" - exit; -fi -printf "found\n" -printf "Checking CXX... " -$CXX --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CXX not found\n" - exit; -fi -printf "found\n" - -printf "Checking endianess... " -printf "int main() { int probe = 0x00000001; return *(char *)&probe; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "Endianess checking failed\n" - exit; -else - ./fake - if [ $? = 1 ] - then - ARCH=le - CXXFLAGS="$CXXFLAGS -DARCH_LE" - CFLAGS="$CFLAGS -DARCH_LE" - printf "Little Endian\n" - else - ARCH=be - CXXFLAGS="$CXXFLAGS -DARCH_BE" - CFLAGS="$CFLAGS -DARCH_BE" - printf "Big Endian\n" - fi -fi -rm -f fake - -printf "Checking for iconv 2nd argument... " -printf "#include \nint main(){ const char** src = 0; iconv(0, src, 0, 0, 0); }\n" > build_check.c -$CC $CFLAGS $LDFLAGS -Werror build_check.c $LIBICONV -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "non-const\n" -else - DEFS="$DEFS -DCONST_ICONV" - printf "const\n" -fi -rm -f fake - -rm -f build_check.c - -printf "OS=$OS\n" > $CONFFILE -printf "STG_TIME=yes\n" >> $CONFFILE -printf "DEBUG=$DEBUG\n" >> $CONFFILE -printf "DIR_BUILD=$BUILD_DIR\n" >> $CONFFILE -printf "DIR_LIB=\$(DIR_BUILD)/../../lib\n" >> $CONFFILE -printf "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs\n" >> $CONFFILE -printf "DIR_INCLUDE=\$(DIR_BUILD)/../../include\n" >> $CONFFILE -printf "ARCH=$ARCH\n" >> $CONFFILE -printf "DEFS=$DEFS\n" >> $CONFFILE -printf "STG_LIBS=" >> $CONFFILE -for lib in $STG_LIBS -do - printf "$lib " >> $CONFFILE -done -printf "\n" >> $CONFFILE -printf "LIB_THREAD=$LIB_THREAD\n" >> $CONFFILE -printf "CC=$CC\n" >> $CONFFILE -printf "CXX=$CXX\n" >> $CONFFILE -printf "CXXFLAGS=$CXXFLAGS\n" >> $CONFFILE -printf "CFLAGS=$CFLAGS\n" >> $CONFFILE -printf "LDFLAGS=$LDFLAGS\n" >> $CONFFILE -printf "LIBICONV=$LIBICONV\n" >> $CONFFILE -printf "PREFIX=$PREFIX\n" >> $CONFFILE -printf "BIN_MODE=$BIN_MODE\n" >> $CONFFILE -printf "DATA_MODE=$DATA_MODE\n" >> $CONFFILE -printf "DIR_MODE=$DIR_MODE\n" >> $CONFFILE -printf "OWNER=$OWNER\n" >> $CONFFILE - -if [ "$1" != "debug" ] -then - $MAKE $MAKEOPTS -else - printf "\n\n\nDebug build. Type $MAKE explicitly\n" -fi diff --git a/projects/rscriptd/listener.cpp b/projects/rscriptd/listener.cpp deleted file mode 100644 index 0b626afd..00000000 --- a/projects/rscriptd/listener.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - * Author : Maxim Mamontov - */ - -#include -#include // readv -#include // for historical versions of BSD -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "stg/scriptexecuter.h" -#include "stg/locker.h" -#include "stg/common.h" -#include "listener.h" - -void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password); -void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8); - -//----------------------------------------------------------------------------- -LISTENER::LISTENER() - : WriteServLog(GetStgLogger()), - port(0), - running(false), - receiverStopped(true), - processorStopped(true), - userTimeout(0), - listenSocket(0), - version("rscriptd listener v.1.2") -{ -pthread_mutex_init(&mutex, NULL); -} -//----------------------------------------------------------------------------- -void LISTENER::SetPassword(const std::string & p) -{ -password = p; -printfd(__FILE__, "Encryption initiated with password \'%s\'\n", password.c_str()); -InitEncrypt(&ctxS, password); -} -//----------------------------------------------------------------------------- -bool LISTENER::Start() -{ -printfd(__FILE__, "LISTENER::Start()\n"); -running = true; - -if (PrepareNet()) - { - return true; - } - -if (receiverStopped) - { - if (pthread_create(&receiverThread, NULL, Run, this)) - { - errorStr = "Cannot create thread."; - return true; - } - } - -if (processorStopped) - { - if (pthread_create(&processorThread, NULL, RunProcessor, this)) - { - errorStr = "Cannot create thread."; - return true; - } - } - -errorStr = ""; - -return false; -} -//----------------------------------------------------------------------------- -bool LISTENER::Stop() -{ -running = false; - -printfd(__FILE__, "LISTENER::Stop()\n"); - -struct timespec ts = {0, 500000000}; -nanosleep(&ts, NULL); - -if (!processorStopped) - { - //5 seconds to thread stops itself - for (int i = 0; i < 25 && !processorStopped; i++) - { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - - //after 5 seconds waiting thread still running. now killing it - if (!processorStopped) - { - //TODO pthread_cancel() - if (pthread_kill(processorThread, SIGINT)) - { - errorStr = "Cannot kill thread."; - return true; - } - printfd(__FILE__, "LISTENER killed Timeouter\n"); - } - } - -if (!receiverStopped) - { - //5 seconds to thread stops itself - for (int i = 0; i < 25 && !receiverStopped; i++) - { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - - //after 5 seconds waiting thread still running. now killing it - if (!receiverStopped) - { - //TODO pthread_cancel() - if (pthread_kill(receiverThread, SIGINT)) - { - errorStr = "Cannot kill thread."; - return true; - } - printfd(__FILE__, "LISTENER killed Run\n"); - } - } - -pthread_join(receiverThread, NULL); -pthread_join(processorThread, NULL); - -pthread_mutex_destroy(&mutex); - -FinalizeNet(); - -std::for_each(users.begin(), users.end(), DisconnectUser(*this)); - -printfd(__FILE__, "LISTENER::Stoped successfully.\n"); - -return false; -} -//----------------------------------------------------------------------------- -void * LISTENER::Run(void * d) -{ -sigset_t signalSet; -sigfillset(&signalSet); -pthread_sigmask(SIG_BLOCK, &signalSet, NULL); - -LISTENER * listener = static_cast(d); - -listener->Runner(); - -return NULL; -} -//----------------------------------------------------------------------------- -void LISTENER::Runner() -{ -receiverStopped = false; - -while (running) - { - RecvPacket(); - } - -receiverStopped = true; -} -//----------------------------------------------------------------------------- -void * LISTENER::RunProcessor(void * d) -{ -sigset_t signalSet; -sigfillset(&signalSet); -pthread_sigmask(SIG_BLOCK, &signalSet, NULL); - -LISTENER * listener = static_cast(d); - -listener->ProcessorRunner(); - -return NULL; -} -//----------------------------------------------------------------------------- -void LISTENER::ProcessorRunner() -{ -processorStopped = false; - -while (running) - { - struct timespec ts = {0, 500000000}; - nanosleep(&ts, NULL); - if (!pending.empty()) - ProcessPending(); - ProcessTimeouts(); - } - -processorStopped = true; -} -//----------------------------------------------------------------------------- -bool LISTENER::PrepareNet() -{ -listenSocket = socket(AF_INET, SOCK_DGRAM, 0); - -if (listenSocket < 0) - { - errorStr = "Cannot create socket."; - return true; - } - -struct sockaddr_in listenAddr; -listenAddr.sin_family = AF_INET; -listenAddr.sin_port = htons(port); -listenAddr.sin_addr.s_addr = inet_addr("0.0.0.0"); - -if (bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)) < 0) - { - errorStr = "LISTENER: Bind failed."; - return true; - } - -printfd(__FILE__, "LISTENER::PrepareNet() >>>> Start successfull.\n"); - -return false; -} -//----------------------------------------------------------------------------- -bool LISTENER::FinalizeNet() -{ -close(listenSocket); - -return false; -} -//----------------------------------------------------------------------------- -bool LISTENER::RecvPacket() -{ -struct iovec iov[2]; - -char buffer[RS_MAX_PACKET_LEN]; -RS::PACKET_HEADER packetHead; - -iov[0].iov_base = reinterpret_cast(&packetHead); -iov[0].iov_len = sizeof(packetHead); -iov[1].iov_base = buffer; -iov[1].iov_len = sizeof(buffer) - sizeof(packetHead); - -size_t dataLen = 0; -while (dataLen < sizeof(buffer)) - { - if (!WaitPackets(listenSocket)) - { - if (!running) - return false; - continue; - } - int portion = readv(listenSocket, iov, 2); - if (portion < 0) - { - return true; - } - dataLen += portion; - } - -if (CheckHeader(packetHead)) - { - printfd(__FILE__, "Invalid packet or incorrect protocol version!\n"); - return true; - } - -std::string userLogin((char *)packetHead.login); -PendingData data; -data.login = userLogin; -data.ip = ntohl(packetHead.ip); -data.id = ntohl(packetHead.id); - -if (packetHead.packetType == RS_ALIVE_PACKET) - { - data.type = PendingData::ALIVE; - } -else if (packetHead.packetType == RS_CONNECT_PACKET) - { - data.type = PendingData::CONNECT; - if (GetParams(buffer, data)) - { - return true; - } - } -else if (packetHead.packetType == RS_DISCONNECT_PACKET) - { - data.type = PendingData::DISCONNECT; - if (GetParams(buffer, data)) - { - return true; - } - } - -STG_LOCKER lock(&mutex); -pending.push_back(data); - -return false; -} -//----------------------------------------------------------------------------- -bool LISTENER::GetParams(char * buffer, UserData & data) -{ -RS::PACKET_TAIL packetTail; - -Decrypt(&ctxS, (char *)&packetTail, buffer, sizeof(packetTail) / 8); - -if (strncmp((char *)packetTail.magic, RS_ID, RS_MAGIC_LEN)) - { - printfd(__FILE__, "Invalid crypto magic\n"); - return true; - } - -std::ostringstream params; -params << "\"" << data.login << "\" " - << inet_ntostring(data.ip) << " " - << data.id << " " - << (char *)packetTail.params; - -data.params = params.str(); - -return false; -} -//----------------------------------------------------------------------------- -void LISTENER::ProcessPending() -{ -std::list::iterator it(pending.begin()); -size_t count = 0; -printfd(__FILE__, "Pending: %d\n", pending.size()); -while (it != pending.end() && count < 256) - { - std::vector::iterator uit( - std::lower_bound( - users.begin(), - users.end(), - it->login) - ); - if (it->type == PendingData::CONNECT) - { - printfd(__FILE__, "Connect packet\n"); - if (uit == users.end() || uit->login != it->login) - { - printfd(__FILE__, "Connect new user '%s'\n", it->login.c_str()); - // Add new user - Connect(*it); - users.insert(uit, AliveData(static_cast(*it))); - } - else if (uit->login == it->login) - { - printfd(__FILE__, "Update existing user '%s'\n", it->login.c_str()); - // Update already existing user - time(&uit->lastAlive); - uit->params = it->params; - } - else - { - printfd(__FILE__, "Hmmm... Strange connect for '%s'\n", it->login.c_str()); - } - } - else if (it->type == PendingData::ALIVE) - { - printfd(__FILE__, "Alive packet\n"); - if (uit != users.end() && uit->login == it->login) - { - printfd(__FILE__, "Alive user '%s'\n", it->login.c_str()); - // Update existing user - time(&uit->lastAlive); - } - else - { - printfd(__FILE__, "Alive user '%s' is not found\n", it->login.c_str()); - } - } - else if (it->type == PendingData::DISCONNECT) - { - printfd(__FILE__, "Disconnect packet\n"); - if (uit != users.end() && uit->login == it->login.c_str()) - { - printfd(__FILE__, "Disconnect user '%s'\n", it->login.c_str()); - // Disconnect existing user - uit->params = it->params; - Disconnect(*uit); - users.erase(uit); - } - else - { - printfd(__FILE__, "Cannot find user '%s' for disconnect\n", it->login.c_str()); - } - } - else - { - printfd(__FILE__, "Unknown packet type\n"); - } - ++it; - ++count; - } -STG_LOCKER lock(&mutex); -pending.erase(pending.begin(), it); -} -//----------------------------------------------------------------------------- -void LISTENER::ProcessTimeouts() -{ -const std::vector::iterator it( - std::stable_partition( - users.begin(), - users.end(), - IsNotTimedOut(userTimeout) - ) - ); - -if (it != users.end()) - { - printfd(__FILE__, "Total users: %d, users to disconnect: %d\n", users.size(), std::distance(it, users.end())); - - std::for_each( - it, - users.end(), - DisconnectUser(*this) - ); - - users.erase(it, users.end()); - } -} -//----------------------------------------------------------------------------- -bool LISTENER::Connect(const UserData & data) const -{ -printfd(__FILE__, "Connect %s\n", data.login.c_str()); -if (access(scriptOnConnect.c_str(), X_OK) == 0) - { - if (ScriptExec((scriptOnConnect + " " + data.params).c_str())) - { - WriteServLog("Script %s cannot be executed for an unknown reason.", scriptOnConnect.c_str()); - return true; - } - } -else - { - WriteServLog("Script %s cannot be executed. File not found.", scriptOnConnect.c_str()); - return true; - } -return false; -} -//----------------------------------------------------------------------------- -bool LISTENER::Disconnect(const UserData & data) const -{ -printfd(__FILE__, "Disconnect %s\n", data.login.c_str()); -if (access(scriptOnDisconnect.c_str(), X_OK) == 0) - { - if (ScriptExec((scriptOnDisconnect + " " + data.params).c_str())) - { - WriteServLog("Script %s cannot be executed for an unknown reson.", scriptOnDisconnect.c_str()); - return true; - } - } -else - { - WriteServLog("Script %s cannot be executed. File not found.", scriptOnDisconnect.c_str()); - return true; - } -return false; -} -//----------------------------------------------------------------------------- -bool LISTENER::CheckHeader(const RS::PACKET_HEADER & header) const -{ -if (strncmp((char *)header.magic, RS_ID, RS_MAGIC_LEN)) - { - return true; - } -if (strncmp((char *)header.protoVer, "02", RS_PROTO_VER_LEN)) - { - return true; - } -return false; -} -//----------------------------------------------------------------------------- -inline -void InitEncrypt(BLOWFISH_CTX * ctx, const std::string & password) -{ -unsigned char keyL[PASSWD_LEN]; -memset(keyL, 0, PASSWD_LEN); -strncpy((char *)keyL, password.c_str(), PASSWD_LEN); -Blowfish_Init(ctx, keyL, PASSWD_LEN); -} -//----------------------------------------------------------------------------- -inline -void Decrypt(BLOWFISH_CTX * ctx, char * dst, const char * src, int len8) -{ -if (dst != src) - memcpy(dst, src, len8 * 8); - -for (int i = 0; i < len8; i++) - Blowfish_Decrypt(ctx, (uint32_t *)(dst + i * 8), (uint32_t *)(dst + i * 8 + 4)); -} -//----------------------------------------------------------------------------- diff --git a/projects/rscriptd/listener.h b/projects/rscriptd/listener.h deleted file mode 100644 index 22b029b6..00000000 --- a/projects/rscriptd/listener.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - * Author : Maxim Mamontov - */ - -#include - -#include -#include -#include -#include - -#include "stg/os_int.h" -#include "stg/blowfish.h" -#include "stg/rs_packets.h" -#include "stg/logger.h" - -struct UserData -{ - std::string params; - std::string login; - uint32_t ip; - uint32_t id; -}; - -struct PendingData : public UserData -{ - enum {CONNECT, ALIVE, DISCONNECT} type; -}; - -struct AliveData : public UserData -{ - explicit AliveData(const UserData & data) - : UserData(data), - lastAlive(time(NULL)) - {}; - bool operator<(const std::string & rvalue) const { return login < rvalue; }; - time_t lastAlive; -}; - -class IsNotTimedOut : public std::unary_function { - public: - explicit IsNotTimedOut(double to) : timeout(to), now(time(NULL)) {} - bool operator()(const AliveData & data) const - { - return difftime(now, data.lastAlive) < timeout; - } - private: - double timeout; - time_t now; -}; - -class LISTENER -{ -public: - LISTENER(); - ~LISTENER(){}; - - void SetPort(uint16_t p) { port = p; }; - void SetPassword(const std::string & p); - void SetUserTimeout(int t) { userTimeout = t; }; - void SetScriptOnConnect(const std::string & script) { scriptOnConnect = script; }; - void SetScriptOnDisconnect(const std::string & script) { scriptOnDisconnect = script; }; - - bool Start(); - bool Stop(); - bool IsRunning() const { return !receiverStopped && !processorStopped; }; - - const std::string & GetStrError() const { return errorStr; }; - const std::string & GetVersion() const { return version; }; - -private: - // Threading stuff - static void * Run(void * self); - static void * RunProcessor(void * self); - void Runner(); - void ProcessorRunner(); - // Networking stuff - bool PrepareNet(); - bool FinalizeNet(); - bool RecvPacket(); - // Parsing stuff - bool CheckHeader(const RS::PACKET_HEADER & header) const; - bool GetParams(char * buffer, UserData & data); - // Processing stuff - void ProcessPending(); - void ProcessTimeouts(); - bool Disconnect(const UserData & data) const; - bool Connect(const UserData & data) const; - - BLOWFISH_CTX ctxS; - STG_LOGGER & WriteServLog; - - mutable std::string errorStr; - std::string scriptOnConnect; - std::string scriptOnDisconnect; - std::string password; - uint16_t port; - - bool running; - bool receiverStopped; - bool processorStopped; - std::vector users; - std::list pending; - int userTimeout; - - pthread_t receiverThread; - pthread_t processorThread; - pthread_mutex_t mutex; - - int listenSocket; - - std::string version; - - friend class DisconnectUser; -}; - -class DisconnectUser : public std::unary_function { - public: - explicit DisconnectUser(LISTENER & l) : listener(l) {}; - void operator()(const UserData & data) - { - listener.Disconnect(data); - }; - private: - LISTENER & listener; -}; -//----------------------------------------------------------------------------- diff --git a/projects/rscriptd/main.cpp b/projects/rscriptd/main.cpp deleted file mode 100644 index 27e4d747..00000000 --- a/projects/rscriptd/main.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - * Author : Maxim Mamontov - */ - - /* - $Revision: 1.19 $ - $Author: faust $ - $Date: 2010/09/10 06:37:45 $ - */ - -#include -#include -#include -#include -#include -#include // creat -#include - -#include -#include -#include -#include -#include // strerror -#include - -#include "stg/common.h" -#include "stg/logger.h" -#include "stg/scriptexecuter.h" -#include "stg/conffiles.h" -#include "stg/version.h" -#include "listener.h" -#include "pidfile.h" - -#ifdef DEBUG -# define MAIN_DEBUG 1 -# define NO_DAEMON 1 -#endif - -#define START_FILE "/._ST_ART_ED_" - -std::set executersPid; -volatile time_t stgTime = time(NULL); - -//----------------------------------------------------------------------------- -void KillExecuters() -{ -std::set::iterator pid; -pid = executersPid.begin(); -while (pid != executersPid.end()) - { - printfd(__FILE__, "KillExecuters pid=%d\n", *pid); - kill(*pid, SIGUSR1); - ++pid; - } -} -//----------------------------------------------------------------------------- -#if defined(LINUX) || defined(DARWIN) -int StartScriptExecuter(char * procName, int msgKey, int * msgID) -#else -int StartScriptExecuter(char *, int msgKey, int * msgID) -#endif -{ -STG_LOGGER & WriteServLog = GetStgLogger(); - -if (*msgID == -11) // If msgID == -11 - first call. Create queue - { - for (int i = 0; i < 2; i++) - { - *msgID = msgget(msgKey, IPC_CREAT | IPC_EXCL | 0600); - - if (*msgID == -1) - { - *msgID = msgget(msgKey, 0); - if (*msgID == -1) - { - WriteServLog("Message queue not created."); - return -1; - } - else - { - msgctl(*msgID, IPC_RMID, NULL); - } - } - else - { - WriteServLog("Message queue created successfully. msgKey=%d msgID=%d", msgKey, *msgID); - break; - } - } - } - -pid_t executerPid = fork(); - -switch (executerPid) - { - case -1: // Failure - WriteServLog("Fork error!"); - return -1; - - case 0: // Child - //close(0); - //close(1); - //close(2); - //setsid(); -#if defined(LINUX) || defined(DARWIN) - Executer(*msgID, executerPid, procName); -#else - Executer(*msgID, executerPid); -#endif - return 1; - - default: // Parent - if (executersPid.empty()) -#if defined(LINUX) || defined(DARWIN) - Executer(*msgID, executerPid, NULL); -#else - Executer(*msgID, executerPid); -#endif - executersPid.insert(executerPid); - } -return 0; -} -//----------------------------------------------------------------------------- -void StopScriptExecuter(int msgID) -{ -STG_LOGGER & WriteServLog = GetStgLogger(); - -for (int i = 0; i < 5; ++i) - { - struct msqid_ds data; - if (msgctl(msgID, IPC_STAT, &data)) - { - int e = errno; - printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e)); - WriteServLog( "Failed to check queue emptiness: '%s'", strerror(e)); - break; - } - - WriteServLog("Messages in queue: %d", data.msg_qnum); - - if (data.msg_qnum == 0) - break; - - struct timespec ts = {1, 0}; - nanosleep(&ts, NULL); - } - -if (msgctl(msgID, IPC_RMID, NULL)) - { - int e = errno; - printfd(__FILE__, "StopScriptExecuter() - msgctl for IPC_STAT failed: '%s'\n", strerror(e)); - WriteServLog("Failed to remove queue: '%s'", strerror(e)); - } -else - { - WriteServLog("Queue removed successfully."); - } - -KillExecuters(); -} -//----------------------------------------------------------------------------- -#ifdef NO_DAEMON -int ForkAndWait(const std::string &) -#else -int ForkAndWait(const std::string & confDir) -#endif -{ -#ifndef NO_DAEMON -pid_t childPid = fork(); - -switch (childPid) - { - case -1: // Failure - return -1; - break; - - case 0: // Child - //close(0); - close(1); - close(2); - setsid(); - break; - - default: // Parent - exit(1); - break; - } -#endif -return 0; -} -//----------------------------------------------------------------------------- -int main(int argc, char * argv[]) -{ -CONFIGFILE * cfg = NULL; -LISTENER * listener = NULL; -int msgID = -11; -int execNum = 0; -int execMsgKey = 0; - -std::string logFileName; -std::string confDir; -std::string password; -std::string onConnect; -std::string onDisconnect; -int port; -int userTimeout; - -if (getuid()) - { - printf("You must be root. Exit.\n"); - exit(1); - } - -if (argc == 2) - cfg = new CONFIGFILE(argv[1]); -else - cfg = new CONFIGFILE("/etc/rscriptd/rscriptd.conf"); - -if (cfg->Error()) - { - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog.SetLogFileName("/var/log/rscriptd.log"); - WriteServLog("Error reading config file!"); - delete cfg; - return EXIT_FAILURE; - } - -cfg->ReadString("LogFileName", &logFileName, "/var/log/rscriptd.log"); -cfg->ReadInt("ExecutersNum", &execNum, 1); -cfg->ReadInt("ExecMsgKey", &execMsgKey, 5555); -cfg->ReadString("ConfigDir", &confDir, "/etc/rscriptd"); -cfg->ReadString("Password", &password, ""); -cfg->ReadInt("Port", &port, 5555); -cfg->ReadInt("UserTimeout", &userTimeout, 60); -cfg->ReadString("ScriptOnConnect", &onConnect, "/etc/rscriptd/OnConnect"); -cfg->ReadString("ScriptOnDisconnect", &onDisconnect, "/etc/rscriptd/OnDisconnect"); - -if (ForkAndWait(confDir) < 0) - { - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog("Fork error!"); - delete cfg; - return EXIT_FAILURE; - } - -STG_LOGGER & WriteServLog = GetStgLogger(); -PIDFile pidFile("/var/run/rscriptd.pid"); -WriteServLog.SetLogFileName(logFileName); -WriteServLog("rscriptd v. %s", SERVER_VERSION); - -for (int i = 0; i < execNum; i++) - { - int ret = StartScriptExecuter(argv[0], execMsgKey, &msgID); - if (ret < 0) - { - STG_LOGGER & WriteServLog = GetStgLogger(); - WriteServLog("Start Script Executer error!"); - delete cfg; - return EXIT_FAILURE; - } - if (ret == 1) - { - delete cfg; - return EXIT_SUCCESS; - } - } - -listener = new LISTENER(); -listener->SetPort(port); -listener->SetPassword(password); -listener->SetUserTimeout(userTimeout); -listener->SetScriptOnConnect(onConnect); -listener->SetScriptOnDisconnect(onDisconnect); - -listener->Start(); - -WriteServLog("rscriptd started successfully."); -WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++"); - -sigset_t signalSet; -sigfillset(&signalSet); -pthread_sigmask(SIG_BLOCK, &signalSet, NULL); - -while (true) - { - sigfillset(&signalSet); - int sig = 0; - printfd(__FILE__, "Before sigwait\n"); - sigwait(&signalSet, &sig); - printfd(__FILE__, "After sigwait. Signal: %d\n", sig); - bool stop = false; - switch (sig) - { - case SIGTERM: - stop = true; - break; - case SIGINT: - stop = true; - break; - default: - WriteServLog("Ignore signel %d", sig); - break; - } - if (stop) - break; - } - -listener->Stop(); - -WriteServLog("+++++++++++++++++++++++++++++++++++++++++++++"); - -StopScriptExecuter(msgID); - -WriteServLog("rscriptd stopped successfully."); -WriteServLog("---------------------------------------------"); - -delete listener; -delete cfg; -return EXIT_SUCCESS; -} -//----------------------------------------------------------------------------- diff --git a/projects/rscriptd/pidfile.cpp b/projects/rscriptd/pidfile.cpp deleted file mode 100644 index 5f3f4979..00000000 --- a/projects/rscriptd/pidfile.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -/* - $Revision: 1.1 $ - $Date: 2010/02/11 12:32:25 $ - $Author: faust $ - */ - -/* - * An implementation of RAII pid-file writer - */ - -#include -#include - -#include "pidfile.h" - -PIDFile::PIDFile(const std::string & fn) - : fileName(fn) -{ -if (fileName != "") - { - std::ofstream pf(fileName.c_str()); - pf << getpid() << std::endl; - pf.close(); - } -} - -PIDFile::~PIDFile() -{ -if (fileName != "") - { - unlink(fileName.c_str()); - } -} diff --git a/projects/rscriptd/pidfile.h b/projects/rscriptd/pidfile.h deleted file mode 100644 index 82ff0038..00000000 --- a/projects/rscriptd/pidfile.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -/* - * Header file for RAII pid-file writer - */ - -/* - $Revision: 1.1 $ - $Date: 2010/02/11 12:32:25 $ - $Author: faust $ - */ - -#ifndef __PID_FILE_H__ -#define __PID_FILE_H__ - -#include - -class PIDFile { -public: - explicit PIDFile(const std::string & fn); - ~PIDFile(); -private: - std::string fileName; -}; - -#endif diff --git a/projects/rscriptd/rscriptd.conf b/projects/rscriptd/rscriptd.conf deleted file mode 100644 index 45b7b5c0..00000000 --- a/projects/rscriptd/rscriptd.conf +++ /dev/null @@ -1,68 +0,0 @@ -################################################################################ -# Rscriptd Configuration file # -################################################################################ - -# LOG file name -# Parameter: optional -# Value: file path -# Default: /var/log/rscriptd.log -LogFileName = /var/log/rscriptd.log - -# Amount of rscriptd-exec processes. -# These processes are responsible for the execution of scripts -# OnConnect and OnDisconnect. -# Amount of processes means how many scripts can be executed simultaneously. -# Recommend to leave 1 to avoid errors when executing scripts -# Parameter: optional -# Value: 1 ... 1024 -# Default: 1 -ExecutersNum = 1 - -# Message queue identifier for the script executer. -# It may be changed if there're a needs to run multiple copies of rscriptd. -# Warning: If you do not understand it, do not touch this setting! -# Parameter: optional -# Value: 0 ... 2 ^ 32 -# Default: 5555 -# ExecMsgKey = 5555 - -# The path to directory where config files are -# Parameter: optional -# Value: directory path -# Default: /etc/rscriptd -ConfigDir = /etc/rscriptd - -# Defines password for the encryption exchange between -# Stargazer server and rscriptd. -# Parameter: optional -# Value: any -# Default: 123456 -Password = 123456 - -# Defines port number for communication between -# Stargazer server and rscriptd. -# Parameter: optional -# Value: 1 ... 65535 -# Default: 9999 -Port = 9999 - -# User timeout. If Stargazer does not respond during this time, -# the user will be disconnected. -# Parameter: optional -# Values: 5 ... 600 -# Default: 60 -UserTimeout = 60 - -# Defines file which runs when user gets access -# Parameter: optional -# Value: file path -# Default: /etc/rscriptd/OnConnect -ScriptOnConnect = /etc/rscriptd/OnConnect - -# Defines file which runs when user loses access -# Parameter: optional -# Value: file path -# Default: /etc/rscriptd/OnDisconnect -ScriptOnDisconnect = /etc/rscriptd/OnDisconnect - -################################################################################ diff --git a/projects/sgauth/.gitignore b/projects/sgauth/.gitignore deleted file mode 100644 index f4bcc898..00000000 --- a/projects/sgauth/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -css.h -sgauth diff --git a/projects/sgauth/Makefile b/projects/sgauth/Makefile deleted file mode 100644 index d6c844e0..00000000 --- a/projects/sgauth/Makefile +++ /dev/null @@ -1,107 +0,0 @@ -############################################################################### -# $Id: Makefile,v 1.18 2009/08/06 12:50:55 faust Exp $ -############################################################################### - -include ../../Makefile.conf - -PROG = sgauth - -SRCS = ./main.cpp \ - ./settings_impl.cpp \ - ./web.cpp - -STGLIBS = conffiles \ - ia \ - crypto \ - common - -STGLIBS_INCS = $(addprefix -I ../../stglibs/,$(addsuffix .lib/include,$(STGLIBS))) -STGLIBS_LIBS = $(addprefix -L ../../stglibs/,$(addsuffix .lib,$(STGLIBS))) - -LIBS += $(addprefix -lstg,$(STGLIBS)) $(LIB_THREAD) $(LIBICONV) - -ifeq ($(OS),linux) -else -LIBS += -lintl \ - -lc -endif - -SEARCH_DIRS = -I ../../include - -OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))) - -CXXFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -CFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -LDFLAGS += $(STGLIBS_LIBS) - -.PHONY: all clean distclean libs install uninstall install-bin install-data uninstall-bin uninstall-data -all: libs $(PROG) ../../Makefile.conf - -libs: - $(MAKE) -C $(DIR_LIBSRC) - -$(PROG): $(OBJS) - $(CXX) $^ $(LDFLAGS) -o $(PROG) $(LIBS) - -clean: - rm -f deps $(PROG) *.o tags *.*~ .OS - rm -f .OS - rm -f .store - rm -f .db.sql - rm -f core* - rm -f css.h - $(MAKE) -C $(DIR_LIBSRC) clean - -distclean: clean - rm -f ../../Makefile.conf - -install: install-bin install-data - -install-bin: -ifeq ($(DEBUG), yes) - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/sbin - install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/sbin/$(PROG) -else - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/sbin - install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG) -endif - $(MAKE) -C $(DIR_LIBSRC) install - -install-data: - # Install etc - mkdir -m $(DIR_MODE) -p $(PREFIX)/etc - install -m $(DATA_MODE) -o $(OWNER) ./sgauth.conf $(PREFIX)/etc/sgauth.conf - -uninstall: uninstall-bin uninstall-data - -uninstall-bin: - rm -f $(PREFIX)/usr/sbin/$(PROG) - -uninstall-data: - # Uninstall etc - rm -f $(PREFIX)/etc/sgauth.conf - - -ifneq ($(MAKECMDGOALS),distclean) -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),uninstall) --include deps -endif -endif -endif - -deps: $(SRCS) ../../Makefile.conf sgauth.css - $(MAKE) -C $(DIR_LIBSRC) - @>deps ;\ - ./make_css.sh ;\ - for file in $(SRCS); do\ - echo "$$file" | grep ".c$$" > /dev/null;\ - if [ $$? -eq 0 ];\ - then\ - echo "`$(CC) $(CFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CC) $(CFLAGS) -c $$<' >> deps ;\ - else\ - echo "`$(CXX) $(CXXFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CXX) $(CXXFLAGS) -c $$<' >> deps ;\ - fi;\ - done diff --git a/projects/sgauth/build b/projects/sgauth/build deleted file mode 100755 index 5f8821b0..00000000 --- a/projects/sgauth/build +++ /dev/null @@ -1,208 +0,0 @@ -#!/bin/sh - -# $Author: faust $ -# $Revision: 1.24 $ -# $Date: 2010/04/14 08:59:02 $ -###################################################### - -OS=unknown -sys=`uname -s` -release=`uname -r` -major=`printf "%s" "$release" | cut -d. -f1` -BUILD_DIR=`pwd` -CONFFILE="../../Makefile.conf" -PREFIX="/" -BIN_MODE=0755 -DATA_MODE=0644 -DIR_MODE=0755 -OWNER=root - -if [ "$1" = "debug" ] -then - DEFS="$DEFS -DDEBUG" - MAKEOPTS="$MAKEOPTS -j1" - CFLAGS="$CFLAGS -ggdb3 -W -Wall -Wextra" - CXXFLAGS="$CXXFLAGS -ggdb3 -W -Wall -Wextra" - DEBUG="yes" -else - DEFS="$DEFS -DNDEBUG" - DEBUG="no" -fi - -CFLAGS="$CFLAGS -I/usr/local/include" -CXXFLAGS="$CXXFLAGS -I/usr/local/include" -LDFLAGS="$LDFLAGS -L/usr/local/lib" - -if [ "$sys" = "Linux" ] -then - OS=linux - MAKE="make" -fi - -if [ "$sys" = "FreeBSD" ] -then - case $major in - 4) OS=bsd;; - 5) OS=bsd5;; - 6) OS=bsd5;; - 7) OS=bsd7;; - *) OS=bsd7;; - esac - MAKE="gmake" -fi - -if [ "$sys" = "Darwin" ] -then - OS=darwin - ETC_DIR="./inst/freebsd/etc/stargazer" - MAKE="gmake" - CFLAGS="$CFLAGS -I/opt/local/include" - CXXFLAGS="$CFLAGS -I/opt/local/include" - LDFLAGS="$LDFLAGS -L/opt/local/lib" -fi - -if [ "$OS" = "unknown" ] -then - printf "#############################################################################\n" - printf "# Sorry, but sgauth is currently supported by Linux, FreeBSD and Darwin. #\n" - printf "#############################################################################\n" - exit 1 -fi - -printf "#############################################################################\n" -printf " Building sgauth for $sys $release\n" -printf "#############################################################################\n" - -STG_LIBS="crypto.lib - common.lib - conffiles.lib - ia.lib" - -if [ "$OS" = "linux" ] -then - DEFS="$DEFS -DLINUX" - LIB_THREAD=-lpthread -else - LIBICONV="-liconv" - if [ "$OS" = "bsd" ] - then - DEFS="$DEFS -DFREE_BSD" - else - if [ "$OS" = "bsd7" ] - then - DEFS="$DEFS -DFREE_BSD5" - LIB_THREAD=-lpthread - else - if [ "$OS" == "darwin" ] - then - DEFS="$DEFS -DDARWIN" - LIB_THREAD=-lpthread - else - LIB_THREAD=-lc_r - fi - fi - fi -fi - -if [ -z "$CC" ] -then - CC=gcc -fi - -if [ -z "$CXX" ] -then - CXX=g++ -fi - -printf "Checking CC... " -$CC --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CC not found\n" - exit; -fi -printf "found\n" -printf "Checking CXX... " -$CXX --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CXX not found\n" - exit; -fi -printf "found\n" - -printf "Checking endianess... " -printf "int main() { int probe = 0x00000001; return *(char *)&probe; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "Endianess checking failed\n" - exit; -else - ./fake - if [ $? = 1 ] - then - ARCH=le - CXXFLAGS="$CXXFLAGS -DARCH_LE" - CFLAGS="$CFLAGS -DARCH_LE" - printf "Little Endian\n" - else - ARCH=be - CXXFLAGS="$CXXFLAGS -DARCH_BE" - CFLAGS="$CFLAGS -DARCH_BE" - printf "Big Endian\n" - fi -fi -rm -f fake - -printf "Checking for iconv 2nd argument... " -printf "#include \nint main(){ const char** src = 0; iconv(0, src, 0, 0, 0); }\n" > build_check.c -$CC $CFLAGS $LDFLAGS -Werror build_check.c $LIBICONV -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "non-const\n" -else - DEFS="$DEFS -DCONST_ICONV" - printf "const\n" -fi -rm -f fake - -rm -f build_check.c - -printf "OS=$OS\n" > $CONFFILE -printf "STG_TIME=yes\n" >> $CONFFILE -printf "DEBUG=$DEBUG\n" >> $CONFFILE -printf "DIR_BUILD=$BUILD_DIR\n" >> $CONFFILE -printf "DIR_LIB=\$(DIR_BUILD)/../../lib\n" >> $CONFFILE -printf "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs\n" >> $CONFFILE -printf "DIR_INCLUDE=\$(DIR_BUILD)/../../include\n" >> $CONFFILE -printf "ARCH=$ARCH\n" >> $CONFFILE -printf "DEFS=$DEFS\n" >> $CONFFILE -printf "STG_LIBS=" >> $CONFFILE -for lib in $STG_LIBS -do - printf "$lib " >> $CONFFILE -done -printf "\n" >> $CONFFILE -printf "LIB_THREAD=$LIB_THREAD\n" >> $CONFFILE -printf "CC=$CC\n" >> $CONFFILE -printf "CXX=$CXX\n" >> $CONFFILE -printf "CXXFLAGS=$CXXFLAGS\n" >> $CONFFILE -printf "CFLAGS=$CFLAGS\n" >> $CONFFILE -printf "LDFLAGS=$LDFLAGS\n" >> $CONFFILE -printf "LIBICONV=$LIBICONV\n" >> $CONFFILE -printf "PREFIX=$PREFIX\n" >> $CONFFILE -printf "BIN_MODE=$BIN_MODE\n" >> $CONFFILE -printf "DATA_MODE=$DATA_MODE\n" >> $CONFFILE -printf "DIR_MODE=$DIR_MODE\n" >> $CONFFILE -printf "OWNER=$OWNER\n" >> $CONFFILE - -if [ "$1" != "debug" ] -then - $MAKE $MAKEOPTS -else - printf "\n\n\nDebug build. Type $MAKE explicitly\n" -fi diff --git a/projects/sgauth/main.cpp b/projects/sgauth/main.cpp deleted file mode 100644 index 3256ae52..00000000 --- a/projects/sgauth/main.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - */ - - /* - $Revision: 1.13 $ - $Date: 2010/04/14 09:01:29 $ - $Author: faust $ - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "stg/ia.h" -#include "stg/common.h" -#include "web.h" -#include "settings_impl.h" - -int mes; -char infoText[256]; -char messageText[256]; - -const int winKOI = 0; - -IA_CLIENT_PROT * clnp; -WEB * web = NULL; - -time_t stgTime; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void Usage() -{ -printf("sgauth \n"); -} -//----------------------------------------------------------------------------- -void SetDirName(const std::vector & dn, void *) -{ -for (int j = 0; j < DIR_NUM; j++) - { - if (winKOI) - { - std::string dir; - KOIToWin(dn[j], &dir); - if (web) - web->SetDirName(dir, j); - } - else - { - if (web) - web->SetDirName(dn[j], j); - } - } -} -//----------------------------------------------------------------------------- -void StatUpdate(const LOADSTAT & ls, void *) -{ -if (web) - web->UpdateStat(ls); -} -//----------------------------------------------------------------------------- -void StatusChanged(int, void *) -{ -} -//----------------------------------------------------------------------------- -void ShowMessage(const std::string & message, int i, int, int, void *) -{ -if (web) - web->AddMessage(message, i); -} -//----------------------------------------------------------------------------- -void ShowError(const std::string & message, int, void *) -{ -if (web) - web->AddMessage(message, 0); -} -//----------------------------------------------------------------------------- -void CatchUSR1(int) -{ -if (clnp->GetAuthorized()) - { - std::cout << "Connect" << std::endl; - clnp->Connect(); - } -} -//----------------------------------------------------------------------------- -void CatchUSR2(int) -{ -std::cout << "Disconnect" << std::endl; -clnp->Disconnect(); -} -//----------------------------------------------------------------------------- -void CatchTERM(int) -{ -std::cout << "Terminated" << std::endl; -clnp->Disconnect(); -sleep(2); -exit(0); -} -//----------------------------------------------------------------------------- -static void SetSignalHandlers() -{ -struct sigaction newsa, oldsa; -sigset_t sigmask; - -sigemptyset(&sigmask); -sigaddset(&sigmask, SIGTERM); -newsa.sa_handler = CatchTERM; -newsa.sa_mask = sigmask; -newsa.sa_flags = 0; -sigaction(SIGTERM, &newsa, &oldsa); - -sigemptyset(&sigmask); -sigaddset(&sigmask, SIGINT); -newsa.sa_handler = CatchTERM; -newsa.sa_mask = sigmask; -newsa.sa_flags = 0; -sigaction(SIGINT, &newsa, &oldsa); - -sigemptyset(&sigmask); -sigaddset(&sigmask, SIGUSR1); -newsa.sa_handler = CatchUSR1; -newsa.sa_mask = sigmask; -newsa.sa_flags = 0; -sigaction(SIGUSR1, &newsa, &oldsa); - -sigemptyset(&sigmask); -sigaddset(&sigmask, SIGUSR2); -newsa.sa_handler = CatchUSR2; -newsa.sa_mask = sigmask; -newsa.sa_flags = 0; -sigaction(SIGUSR2, &newsa, &oldsa); - -return; -} -//----------------------------------------------------------------------------- -int main(int argc, char *argv[]) -{ -SETTINGS_IMPL settings; - -if (argc == 2) - { - settings.SetConfFile(argv[1]); - } -else - { - // Usage - } - -if (settings.ReadSettings()) - { - printf("ReadSettingsError\n"); - printf("%s\n", settings.GetStrError().c_str()); - exit(-1); - } -settings.Print(); - -if (settings.GetDaemon()) - { - switch (fork()) - { - case -1: - exit(1); - break; - - case 0: - setsid(); - break; - - default: - exit(0); - break; - } - } - -clnp = new IA_CLIENT_PROT(settings.GetServerName(), settings.GetServerPort(), settings.GetLocalName(), settings.GetLocalPort()); - -if (!settings.GetNoWeb()) - { - web = new WEB(); - web->SetRefreshPagePeriod(settings.GetRefreshPeriod()); - web->SetListenAddr(settings.GetListenWebIP()); - web->Start(); - } - -clnp->SetLogin(settings.GetLogin()); -clnp->SetPassword(settings.GetPassword()); - -clnp->SetStatusChangedCb(StatusChanged, NULL); -clnp->SetInfoCb(ShowMessage, NULL); -clnp->SetErrorCb(ShowError, NULL); -clnp->SetDirNameCb(SetDirName, NULL); -clnp->SetStatChangedCb(StatUpdate, NULL); -clnp->SetReconnect(settings.GetReconnect()); - -clnp->Start(); - -SetSignalHandlers(); - -#ifdef LINUX -for (int i = 1; i < argc; i++) - memset(argv[i], 0, strlen(argv[i])); - -if(argc > 1) - strcpy(argv[1], "Connecting..."); -#endif - -#ifdef FREEBSD -setproctitle("Connecting..."); -#endif -clnp->Connect(); - -while (1) - { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - - char state[20]; - - if (clnp->GetAuthorized()) - { - if (settings.GetShowPid()) - sprintf(state, "On %d", getpid()); - else - strcpy(state, "Online"); - } - else - { - if (settings.GetShowPid()) - sprintf(state, "Off %d", getpid()); - else - strcpy(state, "Offline"); - } - - #ifdef LINUX - for (int i = 1; i < argc; i++) - memset(argv[i], 0, strlen(argv[i])); - if(argc > 1) - strcpy(argv[1], state); - #endif - - #ifdef FREEBSD - setproctitle(state); - #endif - - #ifdef FREEBSD_5 - setproctitle(state); - #endif - } - -return 0; -} -//----------------------------------------------------------------------------- diff --git a/projects/sgauth/make_css.sh b/projects/sgauth/make_css.sh deleted file mode 100755 index b4de011e..00000000 --- a/projects/sgauth/make_css.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -OUT_FILE=css.h - - -echo "const char * css =" > $OUT_FILE -echo "\"/*------*/\\\\n\"" >> $OUT_FILE -sed -e 's/$/\\n"/g' -e 's/^/"/g' sgauth.css >> $OUT_FILE -echo ";" >> $OUT_FILE - diff --git a/projects/sgauth/settings_impl.cpp b/projects/sgauth/settings_impl.cpp deleted file mode 100644 index 1a7b8dcd..00000000 --- a/projects/sgauth/settings_impl.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#include -#include - -#include "stg/common.h" -#include "stg/conffiles.h" -#include "settings_impl.h" - -SETTINGS_IMPL::SETTINGS_IMPL() - : port(0), - localPort(0), - listenWebIP(0), - refreshPeriod(0), - daemon(false), - noWeb(false), - reconnect(false), - showPid(false), - confFile("/etc/sgauth.conf") -{ -} -//----------------------------------------------------------------------------- -int SETTINGS_IMPL::ReadSettings() -{ -CONFIGFILE cf(confFile); - -if (cf.Error()) - { - strError = "Cannot read file '" + confFile + "'"; - return -1; - } - -cf.ReadString("Login", &login, "/?--?--?*"); -if (login == "/?--?--?*") - { - strError = "Parameter 'Login' not found."; - return -1; - } - -cf.ReadString("Password", &password, "/?--?--?*"); -if (login == "/?--?--?*") - { - strError = "Parameter 'Password' not found."; - return -1; - } - -cf.ReadString("ServerName", &serverName, "?*?*?"); -if (serverName == "?*?*?") - { - strError = "Parameter 'ServerName' not found."; - return -1; - } - -std::string temp; -cf.ReadString("ListenWebIP", &temp, "127.0.0.1"); -listenWebIP = inet_strington(temp); -if (listenWebIP == 0) - { - strError = "Parameter 'ListenWebIP' is not valid."; - return -1; - } - -cf.ReadString("ServerPort", &temp, "5555"); -if (ParseIntInRange(temp, 1, 65535, &port)) - { - strError = "Parameter 'ServerPort' is not valid."; - return -1; - } - -cf.ReadString("LocalName", &localName, ""); - -cf.ReadString("LocalPort", &temp, "0"); -if (ParseIntInRange(temp, 0, 65535, &localPort)) - { - strError = "Parameter 'LocalPort' is not valid."; - return -1; - } - -cf.ReadString("RefreshPeriod", &temp, "5"); -if (ParseIntInRange(temp, 1, 24*3600, &refreshPeriod)) - { - strError = "Parameter 'RefreshPeriod' is not valid."; - return -1; - } - -cf.ReadString("Reconnect", &temp, "yes"); -if (ParseYesNo(temp, &reconnect)) - { - strError = "Parameter 'Reconnect' is not valid."; - return -1; - } - -cf.ReadString("Daemon", &temp, "yes"); -if (ParseYesNo(temp, &daemon)) - { - strError = "Parameter 'Daemon' is not valid."; - return -1; - } - -cf.ReadString("ShowPid", &temp, "no"); -if (ParseYesNo(temp, &showPid)) - { - strError = "Parameter 'ShowPid' is not valid."; - return -1; - } - -cf.ReadString("DisableWeb", &temp, "no"); -if (ParseYesNo(temp, &noWeb)) - { - strError = "Parameter 'DisableWeb' is not valid."; - return -1; - } - -return 0; -} -//----------------------------------------------------------------------------- -void SETTINGS_IMPL::Print() const -{ -std::cout << "Login = " << login << "\n" - << "Password = " << password << "\n" - << "Ip = " << serverName << "\n" - << "Port = " << port << "\n" - << "LocalPort = " << localPort << "\n" - << "ListenWebIP = " << inet_ntostring(listenWebIP) << "\n" - << "RefreshPeriod = " << refreshPeriod << "\n" - << "Daemon = " << daemon << "\n" - << "DisableWeb = " << noWeb << "\n" - << "Reconnect = " << reconnect << "\n" - << "ShowPid = " << showPid << std::endl; -} diff --git a/projects/sgauth/settings_impl.h b/projects/sgauth/settings_impl.h deleted file mode 100644 index 253b69ea..00000000 --- a/projects/sgauth/settings_impl.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef SETTINGS_IMPL_H -#define SETTINGS_IMPL_H - -#include - -#include "stg/os_int.h" - -class SETTINGS_IMPL { -public: - SETTINGS_IMPL(); - ~SETTINGS_IMPL() {} - int Reload() { return 0; } - void SetConfFile(const std::string & cf) { confFile = cf; } - int ReadSettings(); - - const std::string & GetStrError() const { return strError; } - - const std::string & GetServerName() const { return serverName; } - uint16_t GetServerPort() const { return port; } - const std::string & GetLocalName() const { return localName; } - uint16_t GetLocalPort() const { return localPort; } - - const std::string & GetLogin() const { return login; } - const std::string & GetPassword() const { return password; } - - bool GetDaemon() const { return daemon; } - bool GetShowPid() const { return showPid; } - bool GetNoWeb() const { return noWeb; } - bool GetReconnect() const { return reconnect; } - int GetRefreshPeriod() const { return refreshPeriod; } - uint32_t GetListenWebIP() const { return listenWebIP; } - - void Print() const; - -private: - std::string login; - std::string password; - std::string serverName; - int port; - std::string localName; - int localPort; - uint32_t listenWebIP; - int refreshPeriod; - - bool daemon; - bool noWeb; - bool reconnect; - bool showPid; - - std::string confFile; - std::string strError; -}; - -#endif diff --git a/projects/sgauth/sgauth.conf b/projects/sgauth/sgauth.conf deleted file mode 100644 index bb5fca32..00000000 --- a/projects/sgauth/sgauth.conf +++ /dev/null @@ -1,78 +0,0 @@ -################################################################################ -# Sgauth Configuration file # -################################################################################ - -# Stargazer server -# Parameter: required -# Values: IP address or DNS name -# Default: -ServerName = 192.168.1.2 - -# Port on which Stargazer interacts with sgauth -# Parameter: optional -# Value: 1 ... 65535 -# Default: 5555 -ServerPort = 5555 - -# User's login in Stargazer -# Parameter: required -# Value: any -# Default: -Login = test - -# Local host to bind -# Parameter: optional -# Values: IP address or DNS name -# Default: 0.0.0.0 -LocalName = localhost - -# Port on which sgauth interacts with Stargazer -# Parameter: optional -# Value: 1 ... 65535 -# Default: 0 -LocalPort = 12345 - -# User's password in Stargazer -# Parameter: required -# Value: any -# Default: -Password = 123456 - -# Defines whether sgauth should try to reestablish connection to Stargazer -# if it was lost -# Parameter: optional -# Value: yes, no -# Default: yes -Reconnect = yes - -# Defines whether sgauth should run as daemon -# Parameter: optional -# Value: yes, no -# Default: yes -Daemon = yes - -# Web-page refresh period in built-in webserver -# Parameter: optional -# Value: any numeric (minutes) -# Default: 10 -RefreshPeriod = 10 - -# Defines whether sgauth should use built-in webserver -# Parameter: optional -# Value: yes, no -# Default: no -DisableWeb = no - -# Defines address on which sgauth's built-in webserver will listen -# Parameter: optional -# Value: IP address or DNS name -# Default: 127.0.0.1 -ListenWebIP = 127.0.0.1 - -# Defines whether sgauth should show its process ID -# Parameter: optional -# Value: yes, no -# Default: no -ShowPid = no - -################################################################################ diff --git a/projects/sgauth/sgauth.css b/projects/sgauth/sgauth.css deleted file mode 100644 index f816dbf9..00000000 --- a/projects/sgauth/sgauth.css +++ /dev/null @@ -1,78 +0,0 @@ -H3 -{ -color: black; -} - -body -{ -background-color: silver; -} - -#TraffTable -{ -background-color: white; -} - -#TraffTableCaptionRow -{ -background-color: silver; -} - -#TraffTableCaptionCellC, -#TraffTableUMCellC, -#TraffTableDMCellC, -#TraffTableUSCellC, -#TraffTableDSCellC -{ -background-color: silver; -} - -#TraffTableDMRow, -#TraffTableDSRow -{ -background-color: #f2f0cc; -} - -#TraffTableUMRow, -#TraffTableUSRow -{ -background-color: white; -} - -#ConnectionStateOnline -{ -color: green; -font-size: 20px -} - -#ConnectionStateOffline -{ -color: red; -font-size: 20px -} - -p -{ -padding: 2px; -margin: 0px; -} - -#MessagesTable -{ -background-color: white; -} - -#MessagesTableRowC -{ -background-color: silver; -} - - -#MessagesTableRow0, -#MessagesTableRow2, -#MessagesTableRow4, -#MessagesTableRow6, -#MessagesTableRow8 -{ -background-color: #f2f0cc; -} diff --git a/projects/sgauth/web.cpp b/projects/sgauth/web.cpp deleted file mode 100644 index 8c23482b..00000000 --- a/projects/sgauth/web.cpp +++ /dev/null @@ -1,461 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - */ - - /* - $Revision: 1.7 $ - $Date: 2010/03/15 12:58:17 $ - */ - -#include - -#include -#include -#include -#include - -#include "stg/common.h" -#include "stg/ia.h" -#include "web.h" - -extern WEB * web; -extern IA_CLIENT_PROT * clnp; - -#define LISTEN_PORT (5580) - -#include "css.h" - -//--------------------------------------------------------------------------- -#ifndef WIN32 -void * RunWeb(void *) -{ -sigset_t signalSet; -sigfillset(&signalSet); -pthread_sigmask(SIG_BLOCK, &signalSet, NULL); - -#else -unsigned long WINAPI RunWeb(void *) -{ -#endif -while (1) - web->Run(); -return NULL; -} -//--------------------------------------------------------------------------- -WEB::WEB() - : res(0), - listenSocket(0), - outerSocket(0), - refreshPeriod(0), - listenWebAddr(0) -{ -#ifdef WIN32 -res = WSAStartup(MAKEWORD(2,0), &wsaData); -#endif - -for (int i = 0; i < DIR_NUM; i++) - dirName[i] = "-"; - -refreshPeriod = 5; - -memset(&ls, 0, sizeof(ls)); -} -//--------------------------------------------------------------------------- -void WEB::Start() -{ -#ifdef WIN32 -unsigned long pt; -CreateThread( - NULL, // pointer to thread security attributes - 16384, // initial thread stack size, in bytes - RunWeb, // pointer to thread function - NULL, // argument for new thread - 0, // CREATE_SUSPENDED, // creation flags - &pt // pointer to returned thread identifier - ); -#else -pthread_create(&thread, NULL, RunWeb, NULL); -#endif -} -//--------------------------------------------------------------------------- -void WEB::PrepareNet() -{ -listenSocket = socket(PF_INET, SOCK_STREAM, 0); - -struct sockaddr_in listenAddr; -listenAddr.sin_family = AF_INET; -listenAddr.sin_port = htons(LISTEN_PORT); -listenAddr.sin_addr.s_addr = listenWebAddr; - -#ifndef WIN32 -int lng = 1; -if (0 != setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &lng, 4)) - { - printf("Setsockopt Fail\n"); - printf(">>> Error %s\n", strerror(errno)); - } -#else -//??? TODO -#endif - - -res = bind(listenSocket, (struct sockaddr*)&listenAddr, sizeof(listenAddr)); - -if (res == -1) - { - printf("Bind failed.\n"); - exit(0); - } - -res = listen(listenSocket, 0); -if (res == -1) - { - printf("Listen failed.\n"); - exit(0); - } -} -//--------------------------------------------------------------------------- -void WEB::SetRefreshPagePeriod(int p) -{ -refreshPeriod = p; -if (refreshPeriod <= 0 || refreshPeriod > 24*3600) - refreshPeriod = 5; -} -//--------------------------------------------------------------------------- -void WEB::SetListenAddr(uint32_t ip) -{ -listenWebAddr = ip; -} -//--------------------------------------------------------------------------- -void WEB::Run() -{ -PrepareNet(); -char recvBuffer[4096]; -while (1) - { - struct sockaddr_in outerAddr; - - #ifndef WIN32 - socklen_t outerAddrLen = sizeof(outerAddr); - #else - int outerAddrLen = sizeof(outerAddr); - #endif - - outerSocket = accept(listenSocket, (struct sockaddr*)&outerAddr, &outerAddrLen); - if (outerSocket == -1) - { - printf(">>> Error %s\n", strerror(errno)); - continue; - } - recv(outerSocket, recvBuffer, sizeof(recvBuffer), 0); - - if (strncmp(recvBuffer, "GET /sgauth.css", strlen("GET /sgauth.css")) == 0) - { - SendCSS(); - //printf("(1) recvBuffer=%s\n", recvBuffer); - } - else if (strncmp(recvBuffer, "GET /disconnect", strlen("GET /disconnect")) == 0) - { - clnp->Disconnect(); - Redirect("/"); - //printf("(2) recvBuffer=%s\n", recvBuffer); - } - else if (strncmp(recvBuffer, "GET /connect", strlen("GET /connect")) == 0) - { - clnp->Connect(); - Redirect("/"); - //printf("(3) recvBuffer=%s\n", recvBuffer); - } - else if (strncmp(recvBuffer, "GET /exit", strlen("GET /exit")) == 0) - { - Redirect("/"); - clnp->Disconnect(); - #ifdef WIN32 - Sleep(1000); - #else - struct timespec ts = {1, 0}; - nanosleep(&ts, NULL); - #endif - exit(0); - } - else - { - SendReply(); - //printf("(4) recvBuffer=%s\n", recvBuffer); - } - - #ifdef WIN32 - closesocket(outerSocket); - #else - close(outerSocket); - #endif - } -} -//--------------------------------------------------------------------------- -int WEB::Redirect(const char * url) -{ -const char * redirect = - "HTTP/1.0 200 OK\n" - "Content-Type: text/html\n" - "Connection: close" - "\n\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n\n"; - -char buff[2000]; -sprintf(buff, redirect, url); -send(outerSocket, buff, strlen(buff), 0); - -return 0; -} -//--------------------------------------------------------------------------- -int WEB::SendReply() -{ -int j, rowNum; - -const char * replyHeader = - "HTTP/1.0 200 OK\n" - "Content-Type: text/html\n" - "Connection: close" - "\n\n" - "\n" - "\n" - "\n" - "\n" - "sgauth\n" - "" - "\n" - "\n" - "

Stargazer

\n"; - -const char * replyFooter = "\n\n"; - -char replyHeaderBuffer[2000]; -sprintf(replyHeaderBuffer, replyHeader, refreshPeriod); - -send(outerSocket, replyHeaderBuffer, strlen(replyHeaderBuffer), 0); - -char str[512]; - -int st = clnp->GetAuthorized(); - -sprintf(str, "%s

\n", gettext("Connect")); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str, "%s

\n", gettext("Disconnect")); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str, "%s

\n", gettext("Refresh")); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str, "%s

\n", gettext("Exit")); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str, "

%s

\n" , st ? "ConnectionStateOnline":"ConnectionStateOffline", st ? "Online":"Offline"); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str, "

%s: %.3f

\n" , gettext("Cash"), ls.cash / 1000.0); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str, "

%s: %s

\n" , - gettext("PrepaidTraffic"), - ls.freeMb[0] == 'C' ? ls.freeMb + 1 : ls.freeMb); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str, "\n"); -res = send(outerSocket, str, strlen(str), 0); -sprintf(str, " \n"); -res = send(outerSocket, str, strlen(str), 0); -sprintf(str, " \n"); -res = send(outerSocket, str, strlen(str), 0); - -rowNum = 0; -for (j = 0; j < DIR_NUM; j++) - { - if (dirName[j][0] == 0) - continue; - std::string s; - KOIToWin(dirName[j], &s);// +++++++++ sigsegv ========== TODO too long dir name crashes sgauth - sprintf(str, " \n", rowNum++, s.c_str()); - send(outerSocket, str, strlen(str), 0); - } - -sprintf(str," \n"); -send(outerSocket, str, strlen(str), 0); - -sprintf(str," \n"); -send(outerSocket, str, strlen(str), 0); - -sprintf(str," \n", gettext("Month Upload")); -send(outerSocket, str, strlen(str), 0); - -rowNum = 0; -for (j = 0; j < DIR_NUM; j++) - { - if (dirName[j][0] == 0) - continue; - sprintf(str," \n", rowNum++, IntToKMG(ls.mu[j], ST_F)); - res = send(outerSocket, str, strlen(str), 0); - } - -sprintf(str," \n"); -res = send(outerSocket, str, strlen(str), 0); -sprintf(str," \n"); -res = send(outerSocket, str, strlen(str), 0); -sprintf(str," \n", gettext("Month Download")); -res = send(outerSocket, str, strlen(str), 0); - -rowNum = 0; -for (j = 0; j < DIR_NUM; j++) - { - if (dirName[j][0] == 0) - continue; - sprintf(str," \n", rowNum++, IntToKMG(ls.md[j], ST_F)); - res = send(outerSocket, str, strlen(str), 0); - } -sprintf(str," \n"); -res = send(outerSocket, str, strlen(str), 0); - - -sprintf(str," \n"); -res = send(outerSocket, str, strlen(str), 0); -sprintf(str," \n", gettext("Session Upload")); -res = send(outerSocket, str, strlen(str), 0); - -rowNum = 0; -for (j = 0; j < DIR_NUM; j++) - { - if (dirName[j][0] == 0) - continue; - sprintf(str," \n", rowNum++, IntToKMG(ls.su[j], ST_F)); - res = send(outerSocket, str, strlen(str), 0); - } - -sprintf(str," \n"); -res = send(outerSocket, str, strlen(str), 0); -sprintf(str," \n"); -res = send(outerSocket, str, strlen(str), 0); -sprintf(str," \n", gettext("Session Download")); -res = send(outerSocket, str, strlen(str), 0); - -for (j = 0; j < DIR_NUM; j++) - { - if (dirName[j][0] == 0) - continue; - sprintf(str," \n", j, IntToKMG(ls.sd[j], ST_F)); - res = send(outerSocket, str, strlen(str), 0); - } - -sprintf(str," \n"); -res = send(outerSocket, str, strlen(str), 0); - -sprintf(str,"
 %s
%s%s
%s%s
%s%s
%s%s
\n"); -res = send(outerSocket, str, strlen(str), 0); - -rowNum = 0; -if (!messages.empty()) - { - sprintf(str," \n"); - res = send(outerSocket, str, strlen(str), 0); - - sprintf(str," \n"); - send(outerSocket, str, strlen(str), 0); - sprintf(str," \n"); - send(outerSocket, str, strlen(str), 0); - sprintf(str," \n"); - send(outerSocket, str, strlen(str), 0); - sprintf(str," \n"); - send(outerSocket, str, strlen(str), 0); - - std::list::reverse_iterator it; - it = messages.rbegin(); - while (it != messages.rend()) - { - sprintf(str," \n", rowNum); - send(outerSocket, str, strlen(str), 0); - sprintf(str," \n", it->recvTime.c_str()); - send(outerSocket, str, strlen(str), 0); - sprintf(str," \n", it->msg.c_str()); - send(outerSocket, str, strlen(str), 0); - sprintf(str," \n"); - send(outerSocket, str, strlen(str), 0); - ++it; - ++rowNum; - } - - sprintf(str,"
DateText
%s%s
\n"); - res = send(outerSocket, str, strlen(str), 0); - } - -time_t t = time(NULL); -sprintf(str,"Îáíîâëåíî: %s" , ctime(&t)); -res = send(outerSocket, str, strlen(str), 0); - -send(outerSocket, replyFooter, strlen(replyFooter), 0); - -return 0; -} -//--------------------------------------------------------------------------- -int WEB::SendCSS() -{ -const char * replyHeader = - "HTTP/1.0 200 OK\n" - "Content-Type: text/css\n" - "Connection: close\n\n"; - -const char * replyFooter= "\n\n"; - -send(outerSocket, replyHeader, strlen(replyHeader), 0); -send(outerSocket, css, strlen(css), 0); -send(outerSocket, replyFooter, strlen(replyFooter), 0); - -return 0; -} -//--------------------------------------------------------------------------- -void WEB::SetDirName(const std::string & dn, int n) -{ -web->dirName[n] = dn; -} -//--------------------------------------------------------------------------- -void WEB::AddMessage(const std::string & message, int type) -{ -time_t t = time(NULL); -STG_MESSAGE m; - -m.msg = message; -m.type = type; -m.recvTime = ctime(&t); - -messages.push_back(m); - -if (messages.size() > MAX_MESSAGES) - messages.pop_front(); - -} -//--------------------------------------------------------------------------- -void WEB::UpdateStat(const LOADSTAT & ls) -{ -memcpy((void*)&(WEB::ls), &ls, sizeof(LOADSTAT)); -} -//--------------------------------------------------------------------------- - diff --git a/projects/sgauth/web.h b/projects/sgauth/web.h deleted file mode 100644 index a933230a..00000000 --- a/projects/sgauth/web.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - */ - - /* - $Revision: 1.3 $ - $Date: 2007/12/17 08:39:08 $ - */ - -#ifndef WIN32 -#include -#include -#include -#include -#include -#include -#include -#include -#else -#include -#endif - -#include -#include - -#include "stg/const.h" -#include "stg/ia_packets.h" - -#define MAX_MESSAGES (10) -//----------------------------------------------------------------------------- -struct STG_MESSAGE -{ -std::string msg; -std::string recvTime; -int type; -}; -//----------------------------------------------------------------------------- -class WEB -{ -public: - WEB(); - void Run(); - void SetDirName(const std::string & dn, int n); - void SetRefreshPagePeriod(int p); - void SetListenAddr(uint32_t ip); - void AddMessage(const std::string & message, int type); - void UpdateStat(const LOADSTAT & ls); - void Start(); -private: - void PrepareNet(); - int SendReply(); - int SendCSS(); - int Redirect(const char * url); - - #ifdef WIN32 - WSADATA wsaData; - #else - pthread_t thread; - #endif - - std::string dirName[DIR_NUM]; - int res; - int listenSocket; - int outerSocket; - int refreshPeriod; - - uint32_t listenWebAddr; - LOADSTAT ls; - - std::list messages; -}; -//----------------------------------------------------------------------------- diff --git a/projects/sgauthstress/Makefile b/projects/sgauthstress/Makefile deleted file mode 100644 index 74c09b62..00000000 --- a/projects/sgauthstress/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -include ../../Makefile.conf - -PROG = sgauthstress - -SRCS = main.cpp \ - settings.cpp \ - store_loader.cpp \ - user.cpp \ - proto.cpp - -STGLIBS = dotconfpp \ - crypto \ - common - -STGLIBS_INCS = $(addprefix -I ../../stglibs/,$(addsuffix .lib/include,$(STGLIBS))) -STGLIBS_LIBS = $(addprefix -L ../../stglibs/,$(addsuffix .lib,$(STGLIBS))) - -LIBS += $(addprefix -lstg,$(STGLIBS)) $(LIB_THREAD) $(LIBICONV) - -ifeq ($(OS),linux) -LIBS += -ldl -else -LIBS += -lintl \ - -lc -endif - -SEARCH_DIRS = -I ../../include - -OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))) - -CXXFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -CFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -LDFLAGS += -Wl,-E $(STGLIBS_LIBS) - -.PHONY: all clean distclean libs plugins -all: libs plugins $(PROG) ../../Makefile.conf - -libs: - $(MAKE) -C $(DIR_LIBSRC) - -plugins: libs - $(MAKE) -C $(DIR_PLUGINS) - -$(PROG): $(OBJS) - $(CXX) $^ $(LDFLAGS) $(LIBS) -o $(PROG) - -clean: - rm -f deps $(PROG) *.o *.*~ - $(MAKE) -C $(DIR_LIBSRC) clean - $(MAKE) -C $(DIR_PLUGINS) clean - -distclean: clean - rm -f ../../Makefile.conf - -ifneq ($(MAKECMDGOALS),distclean) -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),uninstall) --include deps -endif -endif -endif - -deps: $(SRCS) ../../Makefile.conf - $(MAKE) -C $(DIR_LIBSRC) - @>deps ;\ - for file in $(SRCS); do\ - echo "$$file" | grep ".c$$" > /dev/null;\ - if [ $$? -eq 0 ];\ - then\ - echo "`$(CC) $(CFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CC) $(CFLAGS) -c $$<' >> deps ;\ - else\ - echo "`$(CXX) $(CXXFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CXX) $(CXXFLAGS) -c $$<' >> deps ;\ - fi;\ - done diff --git a/projects/sgauthstress/build b/projects/sgauthstress/build deleted file mode 100755 index dae35b74..00000000 --- a/projects/sgauthstress/build +++ /dev/null @@ -1,375 +0,0 @@ -#!/bin/sh - -# $Author: faust $ -# $Revision: 1.24 $ -# $Date: 2010/04/14 08:59:02 $ -###################################################### - -OS=unknown -sys=`uname -s` -release=`uname -r` -major=`printf "%s" "$release" | cut -d. -f1` -BUILD_DIR=`pwd` -CONFFILE="../../Makefile.conf" -PREFIX="/" -BIN_MODE=0755 -DATA_MODE=0644 -DIR_MODE=0755 -OWNER=root - -if [ "$1" = "debug" ] -then - DEFS="$DEFS -DDEBUG" - MAKEOPTS="$MAKEOPTS -j1" - CFLAGS="$CFLAGS -ggdb3 -W -Wall -Wextra" - CXXFLAGS="$CXXFLAGS -ggdb3 -W -Wall -Wextra" - DEBUG="yes" -else - DEFS="$DEFS -DNDEBUG" - DEBUG="no" -fi - -CFLAGS="$CFLAGS -I/usr/local/include" -CXXFLAGS="$CXXFLAGS -I/usr/local/include" -LDFLAGS="$LDFLAGS -L/usr/local/lib" - -if [ "$sys" = "Linux" ] -then - OS=linux - MAKE="make" -fi - -if [ "$sys" = "FreeBSD" ] -then - case $major in - 4) OS=bsd;; - 5) OS=bsd5;; - 6) OS=bsd5;; - 7) OS=bsd7;; - *) OS=bsd7;; - esac - MAKE="gmake" -fi - -if [ "$sys" = "Darwin" ] -then - OS=darwin - ETC_DIR="./inst/freebsd/etc/stargazer" - MAKE="gmake" - CFLAGS="$CFLAGS -I/opt/local/include" - CXXFLAGS="$CFLAGS -I/opt/local/include" - LDFLAGS="$LDFLAGS -L/opt/local/lib" -fi - -if [ "$OS" = "unknown" ] -then - printf "################################################################################\n" - printf "# Sorry, but sgauthstress is currently supported by Linux, FreeBSD and Darwin. #\n" - printf "################################################################################\n" - exit 1 -fi - -printf "#############################################################################\n" -printf " Building sgauthstress for $sys $release\n" -printf "#############################################################################\n" - -STG_LIBS="logger.lib - crypto.lib - common.lib - conffiles.lib - dotconfpp.lib" - -PLUGINS="store/files" - -if [ "$OS" = "linux" ] -then - DEFS="$DEFS -DLINUX" - LIB_THREAD=-lpthread -else - LIBICONV="-liconv" - if [ "$OS" = "bsd" ] - then - DEFS="$DEFS -DFREE_BSD" - LIB_THREAD=-lc_r - else - DEFS="$DEFS -DFREE_BSD5" - if [ "$OS" = "bsd7" ] - then - LIB_THREAD=-lpthread - else - LIB_THREAD=-lc_r - fi - fi -fi - -if [ -z "$CC" ] -then - CC=gcc -fi - -if [ -z "$CXX" ] -then - CXX=g++ -fi - -printf "Checking CC... " -$CC --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CC not found\n" - exit; -fi -printf "found\n" -printf "Checking CXX... " -$CXX --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CXX not found\n" - exit; -fi -printf "found\n" - -printf "Checking endianess... " -printf "int main() { int probe = 0x00000001; return *(char *)&probe; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "Endianess checking failed\n" - exit; -else - ./fake - if [ $? = 1 ] - then - ARCH=le - CXXFLAGS="$CXXFLAGS -DARCH_LE" - CFLAGS="$CFLAGS -DARCH_LE" - printf "Little Endian\n" - else - ARCH=be - CXXFLAGS="$CXXFLAGS -DARCH_BE" - CFLAGS="$CFLAGS -DARCH_BE" - printf "Big Endian\n" - fi -fi -rm -f fake - -printf "Checking for iconv 2nd argument... " -printf "#include \nint main(){ const char** src = 0; iconv(0, src, 0, 0, 0); }\n" > build_check.c -$CC $CFLAGS $LDFLAGS -Werror build_check.c $LIBICONV -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "non-const\n" -else - DEFS="$DEFS -DCONST_ICONV" - printf "const\n" -fi -rm -f fake - -rm -f build_check.c - -printf "Checking for fb_config... " -FB_VERSION=`fb_config --version 2> /dev/null` -if [ "$?" != "0" ] -then - printf "no\n" - printf "Checking for -lfbclient... " - printf "int main() { return 0; }\n" > build_check.c - $CC $CFLAGS $LDFLAGS build_check.c -lfbclient $LIB_THREAD -o fake > /dev/null 2> /dev/null - if [ $? != 0 ] - then - CHECK_FBCLIENT=no - printf "no\n" - else - FB_CFLAGS="" - FB_LDFLAGS="-lfbclient" - CHECK_FBCLIENT=yes - printf "yes\n" - fi - rm -f fake -else - printf "yes\n" - printf "Checking for fb_config --cflags... " - FB_CFLAGS=`fb_config --cflags` - if [ "$?" != "0" ] - then - CHECK_FBCLIENT=no - printf "no\n" - else - printf "[$FB_CFLAGS]\n" - printf "Checking for fb_config --libs " - FB_LDFLAGS=`fb_config --libs` - if [ "$?" != "0" ] - then - CHECK_FBCLIENT=no - printf "no\n" - else - CHECK_FBCLIENT=yes - printf "[$FB_LDFLAGS]\n" - fi - fi -fi - -printf "Checking for mysql_config... " -MYSQL_VERSION=`mysql_config --version 2> /dev/null` -if [ $? != 0 ] -then - printf "no\n"; - printf "Checking for -lmysqlclient... " - $CC $CFLAGS $LDFLAGS build_check.c -lmysqlclient_r $LIB_THREAD -o fake > /dev/null 2> /dev/null - if [ $? != 0 ] - then - CHECK_MYSQLCLIENT=no - printf "no\n" - else - CHECK_MYSQLCLIENT=yes - printf "yes\n" - fi - rm -f fake -else - printf "yes\n" - printf "Checking for mysql_config --cflags... " - MYSQL_CFLAGS=`mysql_config --cflags 2> /dev/null` - if [ $? != 0 ] - then - CHECK_MYSQLCLIENT=no - printf "no\n" - else - printf "[$MYSQL_CFLAGS]\n" - printf "Checking for mysql_config --libs_r... " - MYSQL_LDFLAGS=`mysql_config --libs_r 2> /dev/null` - if [ $? != 0 ] - then - CHECK_MYSQLCLIENT=no - printf "no\n" - else - CHECK_MYSQLCLIENT=yes - printf "[$MYSQL_LDFLAGS]\n" - fi - fi -fi - -printf "Checking for pg_config... " -printf "#include \nint main() { return 0; }\n" > build_check.c -PG_VERSION=`pg_config --version 2> /dev/null` -if [ $? != 0 ] -then - printf "no\n"; - printf "Checking for -lpq... " - $CC $CFLAGS $LDFLAGS build_check.c -lpq $LIB_THREAD -o fake > /dev/null 2> /dev/null - if [ $? != 0 ] - then - CHECK_PQ=no - printf "no\n" - else - CHECK_PQ=yes - printf "yes\n" - fi - rm -f fake -else - printf "yes\n"; - printf "Checking for pg_config --includedir... " - PG_CFLAGS="-I"`pg_config --includedir 2> /dev/null` - if [ $? != 0 ] - then - CHECK_PQ=no - printf "no\n" - else - printf "[$PG_CFLAGS]\n" - printf "Checking for pg_config --libdir... " - PG_LDFLAGS="-L"`pg_config --libdir 2> /dev/null` - if [ $? != 0 ] - then - CHECK_PQ=no - printf "no\n" - else - CHECK_PQ=yes - printf "[$PG_LDFLAGS]\n" - fi - fi -fi - -rm -f build_check.c - -if [ "$CHECK_FBCLIENT" = "yes" ] -then - STG_LIBS="$STG_LIBS - ibpp.lib" - PLUGINS="$PLUGINS - store/firebird" -fi - -if [ "$CHECK_PQ" = "yes" ] -then - PLUGINS="$PLUGINS - store/postgresql" -fi - -if [ "$CHECK_MYSQLCLIENT" = "yes" ] -then - PLUGINS="$PLUGINS - store/mysql" -fi - -printf "OS=$OS\n" > $CONFFILE -printf "STG_TIME=yes\n" >> $CONFFILE -printf "DEBUG=$DEBUG\n" >> $CONFFILE -printf "DIR_BUILD=$BUILD_DIR\n" >> $CONFFILE -printf "DIR_LIB=\$(DIR_BUILD)/../../lib\n" >> $CONFFILE -printf "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs\n" >> $CONFFILE -printf "DIR_INCLUDE=\$(DIR_BUILD)/../../include\n" >> $CONFFILE -printf "DIR_MOD=\$(DIR_BUILD)/../stargazer/modules\n" >> $CONFFILE -printf "DIR_PLUGINS=\$(DIR_BUILD)/../stargazer/plugins\n" >> $CONFFILE -printf "ARCH=$ARCH\n" >> $CONFFILE -printf "CHECK_FBCLIENT=$CHECK_FBCLIENT\n" >> $CONFFILE -if [ "$CHECK_FBCLIENT" = "yes" ] -then - printf "FB_CFLAGS=$FB_CFLAGS\n" >> $CONFFILE - printf "FB_LDFLAGS=$FB_LDFLAGS\n" >> $CONFFILE -fi -printf "CHECK_MYSQLCLIENT=$CHECK_MYSQLCLIENT\n" >> $CONFFILE -if [ "$CHECK_MYSQLCLIENT" = "yes" ] -then - printf "MYSQL_CFLAGS=$MYSQL_CFLAGS\n" >> $CONFFILE - printf "MYSQL_LDFLAGS=$MYSQL_LDFLAGS\n" >> $CONFFILE -fi -printf "CHECK_PQ=$CHECK_PQ\n" >> $CONFFILE -if [ "$CHECK_PQ" = "yes" ] -then - printf "PG_CFLAGS=$PG_CFLAGS\n" >> $CONFFILE - printf "PG_LDFLAGS=$PG_LDFLAGS\n" >> $CONFFILE -fi -printf "DEFS=$DEFS\n" >> $CONFFILE -printf "STG_LIBS=" >> $CONFFILE -for lib in $STG_LIBS -do - printf "$lib " >> $CONFFILE -done -printf "\n" >> $CONFFILE -printf "PLUGINS=" >> $CONFFILE -for plugin in $PLUGINS -do - printf "$plugin " >> $CONFFILE -done -printf "\n" >> $CONFFILE -printf "LIB_THREAD=$LIB_THREAD\n" >> $CONFFILE -printf "CC=$CC\n" >> $CONFFILE -printf "CXX=$CXX\n" >> $CONFFILE -printf "CXXFLAGS=$CXXFLAGS\n" >> $CONFFILE -printf "CFLAGS=$CFLAGS\n" >> $CONFFILE -printf "LDFLAGS=$LDFLAGS\n" >> $CONFFILE -printf "LIBICONV=$LIBICONV\n" >> $CONFFILE -printf "PREFIX=$PREFIX\n" >> $CONFFILE -printf "BIN_MODE=$BIN_MODE\n" >> $CONFFILE -printf "DATA_MODE=$DATA_MODE\n" >> $CONFFILE -printf "DIR_MODE=$DIR_MODE\n" >> $CONFFILE -printf "OWNER=$OWNER\n" >> $CONFFILE - -if [ "$1" != "debug" ] -then - $MAKE $MAKEOPTS -else - printf "\n\n\nDebug build. Type $MAKE explicitly\n" -fi diff --git a/projects/sgauthstress/main.cpp b/projects/sgauthstress/main.cpp deleted file mode 100644 index b0819c3c..00000000 --- a/projects/sgauthstress/main.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - */ - - /* - $Revision: 1.13 $ - $Date: 2010/04/14 09:01:29 $ - $Author: faust $ - */ - -#include - -#include -#include -#include -#include - -#include "stg/common.h" -#include "stg/store.h" -#include "stg/user_conf.h" - -#include "settings.h" -#include "store_loader.h" -#include "proto.h" -#include "user.h" - -time_t stgTime; -bool running; - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- -void Usage() -{ -std::cout << "Usage:\n\nsgauth " << std::endl; -} -//----------------------------------------------------------------------------- -void CatchTERM(int) -{ -running = false; -} -//----------------------------------------------------------------------------- -static void SetSignalHandlers() -{ -struct sigaction newsa, oldsa; -sigset_t sigmask; - -sigemptyset(&sigmask); -sigaddset(&sigmask, SIGTERM); -newsa.sa_handler = CatchTERM; -newsa.sa_mask = sigmask; -newsa.sa_flags = 0; -sigaction(SIGTERM, &newsa, &oldsa); - -sigemptyset(&sigmask); -sigaddset(&sigmask, SIGINT); -newsa.sa_handler = CatchTERM; -newsa.sa_mask = sigmask; -newsa.sa_flags = 0; -sigaction(SIGINT, &newsa, &oldsa); - -return; -} -//----------------------------------------------------------------------------- -int main(int argc, char *argv[]) -{ -SETTINGS settings; - -if (argc == 2) - { - settings.SetConfFile(argv[1]); - } - -if (settings.ReadSettings()) - { - std::cerr << "Failed to read settings: '" - << settings.GetStrError() << "'" << std::endl; - Usage(); - return -1; - } - -SetSignalHandlers(); - -PROTO proto(settings.GetServerName(), - settings.GetServerPort(), - settings.GetLocalPort(), - 10); - -STORE_LOADER storeLoader(settings.GetModulesPath(), settings.GetStoreModuleSettings()); -if (storeLoader.Load()) - { - std::cerr << "Failed to load storage plugin: '" << storeLoader.GetStrError() << "'" << std::endl; - return -1; - } - -STORE * dataStore = storeLoader.GetStore(); - -std::vector userList; -if (dataStore->GetUsersList(&userList)) - { - std::cerr << "Failed to get user list: '" << dataStore->GetStrError() << "'" << std::endl; - return -1; - } - -std::list ips; - { - std::vector::const_iterator it; - for (it = userList.begin(); it != userList.end(); ++it) - { - USER_CONF userConf; - if (dataStore->RestoreUserConf(&userConf, *it)) - { - std::cerr << "Failed to read user conf: '" << dataStore->GetStrError() << "'" << std::endl; - return -1; - } - proto.AddUser( - USER( - *it, - userConf.password, - userConf.ips[0].ip - ) - ); - ips.push_back(userConf.ips[0].ip); - } - } - -if (!proto.Start()) - { - std::cerr << "Failed to start listening thread: '" << proto.GetStrError() << "'" << std::endl; - return -1; - } - -std::list::const_iterator it; -for (it = ips.begin(); it != ips.end(); ++it) - { - proto.Connect(*it); - } - -std::cout << "Successfully loaded " << proto.UserCount() << " users" << std::endl; - -running = true; -while (running) - { - struct timespec ts = {0, 200000000}; - nanosleep(&ts, NULL); - } - -proto.Stop(); - -storeLoader.Unload(); - -return 0; -} -//----------------------------------------------------------------------------- diff --git a/projects/sgauthstress/mkifs.sh b/projects/sgauthstress/mkifs.sh deleted file mode 100755 index ada22f00..00000000 --- a/projects/sgauthstress/mkifs.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -users=`cat users.1000` -hi=0 -lo=0 -for user in $users -do - if (( $lo > 254 )) - then - lo=0 - let hi++ - fi - let lo++ - ip="10.22.$hi.$lo" - ip addr add $ip dev eth0 -done diff --git a/projects/sgauthstress/proto.cpp b/projects/sgauthstress/proto.cpp deleted file mode 100644 index d1114f17..00000000 --- a/projects/sgauthstress/proto.cpp +++ /dev/null @@ -1,574 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "stg/common.h" -#include "stg/ia_packets.h" -#include "stg/locker.h" - -#include "proto.h" - -class HasIP : public std::unary_function, bool> { - public: - explicit HasIP(uint32_t i) : ip(i) {} - bool operator()(const std::pair & value) { return value.first == ip; } - private: - uint32_t ip; -}; - -PROTO::PROTO(const std::string & server, - uint16_t port, - uint16_t localPort, - int to) - : timeout(to), - running(false), - stopped(true) -{ -uint32_t ip = inet_addr(server.c_str()); -if (ip == INADDR_NONE) - { - struct hostent * hePtr = gethostbyname(server.c_str()); - if (hePtr) - { - ip = *((uint32_t *)hePtr->h_addr_list[0]); - } - else - { - errorStr = "Unknown host: '"; - errorStr += server; - errorStr += "'"; - printfd(__FILE__, "PROTO::PROTO() - %s\n", errorStr.c_str()); - throw std::runtime_error(errorStr); - } - } - -localAddr.sin_family = AF_INET; -localAddr.sin_port = htons(localPort); -localAddr.sin_addr.s_addr = inet_addr("0.0.0.0"); - -serverAddr.sin_family = AF_INET; -serverAddr.sin_port = htons(port); -serverAddr.sin_addr.s_addr = ip; - -unsigned char key[IA_PASSWD_LEN]; -memset(key, 0, IA_PASSWD_LEN); -strncpy(reinterpret_cast(key), "pr7Hhen", 8); -Blowfish_Init(&ctx, key, IA_PASSWD_LEN); - -processors["CONN_SYN_ACK"] = &PROTO::CONN_SYN_ACK_Proc; -processors["ALIVE_SYN"] = &PROTO::ALIVE_SYN_Proc; -processors["DISCONN_SYN_ACK"] = &PROTO::DISCONN_SYN_ACK_Proc; -processors["FIN"] = &PROTO::FIN_Proc; -processors["INFO"] = &PROTO::INFO_Proc; -// ERR_Proc will be handled explicitly - -pthread_mutex_init(&mutex, NULL); -} - -PROTO::~PROTO() -{ -pthread_mutex_destroy(&mutex); -} - -void * PROTO::Runner(void * data) -{ -sigset_t signalSet; -sigfillset(&signalSet); -pthread_sigmask(SIG_BLOCK, &signalSet, NULL); - -PROTO * protoPtr = static_cast(data); -protoPtr->Run(); -return NULL; -} - -bool PROTO::Start() -{ -stopped = false; -running = true; -if (pthread_create(&tid, NULL, &Runner, this)) - { - errorStr = "Failed to create listening thread: '"; - errorStr += strerror(errno); - errorStr += "'"; - printfd(__FILE__, "PROTO::Start() - %s\n", errorStr.c_str()); - return false; - } -return true; -} - -bool PROTO::Stop() -{ -running = false; -int time = 0; -while (!stopped && time < timeout) - { - struct timespec ts = {1, 0}; - nanosleep(&ts, NULL); - ++time; - } -if (!stopped) - { - errorStr = "Failed to stop listening thread - timed out"; - printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str()); - return false; - } -if (pthread_join(tid, NULL)) - { - errorStr = "Failed to join listening thread after stop: '"; - errorStr += strerror(errno); - errorStr += "'"; - printfd(__FILE__, "PROTO::Stop() - %s\n", errorStr.c_str()); - return false; - } -return true; -} - -void PROTO::AddUser(const USER & user, bool connect) -{ -STG_LOCKER lock(&mutex); -users.push_back(std::make_pair(user.GetIP(), user)); -users.back().second.InitNetwork(); - -struct pollfd pfd; -pfd.fd = users.back().second.GetSocket(); -pfd.events = POLLIN; -pfd.revents = 0; -pollFds.push_back(pfd); - -if (connect) - { - RealConnect(&users.back().second); - } -} - -bool PROTO::Connect(uint32_t ip) -{ -std::list >::iterator it; -STG_LOCKER lock(&mutex); -it = std::find_if(users.begin(), users.end(), HasIP(ip)); -if (it == users.end()) - return false; - -// Do something - -return RealConnect(&it->second); -} - -bool PROTO::Disconnect(uint32_t ip) -{ -std::list >::iterator it; -STG_LOCKER lock(&mutex); -it = std::find_if(users.begin(), users.end(), HasIP(ip)); -if (it == users.end()) - return false; - -// Do something - -return RealDisconnect(&it->second); -} - -void PROTO::Run() -{ -while (running) - { - int res; - { - STG_LOCKER lock(&mutex); - res = poll(&pollFds.front(), pollFds.size(), timeout); - } - if (res < 0) - break; - if (!running) - break; - if (res) - { - printfd(__FILE__, "PROTO::Run() - events: %d\n", res); - RecvPacket(); - } - else - { - CheckTimeouts(); - } - } - -stopped = true; -} - -void PROTO::CheckTimeouts() -{ -STG_LOCKER lock(&mutex); -std::list >::iterator it; -for (it = users.begin(); it != users.end(); ++it) - { - int delta = difftime(time(NULL), it->second.GetPhaseChangeTime()); - if ((it->second.GetPhase() == 3) && - (delta > it->second.GetUserTimeout())) - { - printfd(__FILE__, "PROTO::CheckTimeouts() - user alive timeout (ip: %s, login: '%s', delta: %d > %d)\n", inet_ntostring(it->second.GetIP()).c_str(), it->second.GetLogin().c_str(), delta, it->second.GetUserTimeout()); - it->second.SetPhase(1); - } - if ((it->second.GetPhase() == 2) && - (delta > it->second.GetAliveTimeout())) - { - printfd(__FILE__, "PROTO::CheckTimeouts() - user connect timeout (ip: %s, login: '%s', delta: %d > %d)\n", inet_ntostring(it->second.GetIP()).c_str(), it->second.GetLogin().c_str(), delta, it->second.GetAliveTimeout()); - it->second.SetPhase(1); - } - } -} - -bool PROTO::RecvPacket() -{ -bool result = true; -std::vector::iterator it; -std::list >::iterator userIt; -STG_LOCKER lock(&mutex); -for (it = pollFds.begin(), userIt = users.begin(); it != pollFds.end() && userIt != users.end(); ++it, ++userIt) - { - if (it->revents) - { - it->revents = 0; - assert(it->fd == userIt->second.GetSocket() && "File descriptors from poll fds and users must be syncked"); - struct sockaddr_in addr; - socklen_t fromLen = sizeof(addr); - char buffer[2048]; - int res = recvfrom(userIt->second.GetSocket(), buffer, sizeof(buffer), 0, (struct sockaddr *)&addr, &fromLen); - - if (res == -1) - { - result = false; - continue; - } - - result = result && HandlePacket(buffer, res, &(userIt->second)); - } - } - -return result; -} - -bool PROTO::HandlePacket(const char * buffer, size_t length, USER * user) -{ -if (!strncmp(buffer + 4 + sizeof(HDR_8), "ERR", 3)) - { - return ERR_Proc(buffer, user); - } - -for (size_t i = 0; i < length / 8; i++) - Blowfish_Decrypt(user->GetCtx(), - (uint32_t *)(buffer + i * 8), - (uint32_t *)(buffer + i * 8 + 4)); - -std::string packetName(buffer + 12); - -std::map::const_iterator it; -it = processors.find(packetName); -if (it != processors.end()) - return (this->*it->second)(buffer, user); - -printfd(__FILE__, "PROTO::HandlePacket() - invalid packet signature: '%s'\n", packetName.c_str()); - -return false; -} - -bool PROTO::CONN_SYN_ACK_Proc(const void * buffer, USER * user) -{ -const CONN_SYN_ACK_8 * packet = static_cast(buffer); - -uint32_t rnd = packet->rnd; -uint32_t userTimeout = packet->userTimeOut; -uint32_t aliveTimeout = packet->aliveDelay; - -#ifdef ARCH_BE -SwapBytes(rnd); -SwapBytes(userTimeout); -SwapBytes(aliveDelay); -#endif - -if (user->GetPhase() != 2) - { - errorStr = "Unexpected CONN_SYN_ACK"; - printfd(__FILE__, "PROTO::CONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase()); - return false; - } - -user->SetPhase(3); -user->SetAliveTimeout(aliveTimeout); -user->SetUserTimeout(userTimeout); -user->SetRnd(rnd); - -Send_CONN_ACK(user); - -printfd(__FILE__, "PROTO::CONN_SYN_ACK_Proc() - user '%s' successfully logged in from IP %s\n", user->GetLogin().c_str(), inet_ntostring(user->GetIP()).c_str()); - -return true; -} - -bool PROTO::ALIVE_SYN_Proc(const void * buffer, USER * user) -{ -const ALIVE_SYN_8 * packet = static_cast(buffer); - -uint32_t rnd = packet->rnd; - -#ifdef ARCH_BE -SwapBytes(rnd); -#endif - -if (user->GetPhase() != 3) - { - errorStr = "Unexpected ALIVE_SYN"; - printfd(__FILE__, "PROTO::ALIVE_SYN_Proc() - wrong phase: %d\n", user->GetPhase()); - return false; - } - -user->SetPhase(3); -user->SetRnd(rnd); // Set new rnd value for ALIVE_ACK - -Send_ALIVE_ACK(user); - -return true; -} - -bool PROTO::DISCONN_SYN_ACK_Proc(const void * buffer, USER * user) -{ -const DISCONN_SYN_ACK_8 * packet = static_cast(buffer); - -uint32_t rnd = packet->rnd; - -#ifdef ARCH_BE -SwapBytes(rnd); -#endif - -if (user->GetPhase() != 4) - { - errorStr = "Unexpected DISCONN_SYN_ACK"; - printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong phase: %d\n", user->GetPhase()); - return false; - } - -if (user->GetRnd() + 1 != rnd) - { - errorStr = "Wrong control value at DISCONN_SYN_ACK"; - printfd(__FILE__, "PROTO::DISCONN_SYN_ACK_Proc() - wrong control value: %d, expected: %d\n", rnd, user->GetRnd() + 1); - } - -user->SetPhase(5); -user->SetRnd(rnd); - -Send_DISCONN_ACK(user); - -return true; -} - -bool PROTO::FIN_Proc(const void * buffer, USER * user) -{ -if (user->GetPhase() != 5) - { - errorStr = "Unexpected FIN"; - printfd(__FILE__, "PROTO::FIN_Proc() - wrong phase: %d\n", user->GetPhase()); - return false; - } - -user->SetPhase(1); - -return true; -} - -bool PROTO::INFO_Proc(const void * buffer, USER * user) -{ -//const INFO_8 * packet = static_cast(buffer); - -return true; -} - -bool PROTO::ERR_Proc(const void * /*buffer*/, USER * user) -{ -//uint32_t len = packet->len; - -#ifdef ARCH_BE -//SwapBytes(len); -#endif - -user->SetPhase(1); //TODO: Check -/*KOIToWin((const char*)err.text, &messageText); -if (pErrorCb != NULL) - pErrorCb(messageText, IA_SERVER_ERROR, errorCbData); -phaseTime = GetTickCount(); -codeError = IA_SERVER_ERROR;*/ - -return true; -} - -bool PROTO::Send_CONN_SYN(USER * user) -{ -CONN_SYN_8 packet; - -packet.len = sizeof(packet); - -#ifdef ARCH_BE -SwapBytes(packet.len); -#endif - -strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS)); -strncpy((char *)packet.type, "CONN_SYN", sizeof(packet.type)); -strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login)); -packet.dirs = 0xFFffFFff; - -return SendPacket(&packet, sizeof(packet), user); -} - -bool PROTO::Send_CONN_ACK(USER * user) -{ -CONN_ACK_8 packet; - -packet.len = sizeof(packet); -packet.rnd = user->IncRnd(); - -#ifdef ARCH_BE -SwapBytes(packet.len); -SwapBytes(packet.rnd); -#endif - -strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS)); -strncpy((char *)packet.type, "CONN_ACK", sizeof(packet.type)); - -return SendPacket(&packet, sizeof(packet), user); -} - -bool PROTO::Send_ALIVE_ACK(USER * user) -{ -ALIVE_ACK_8 packet; - -packet.len = sizeof(packet); -packet.rnd = user->IncRnd(); - -#ifdef ARCH_BE -SwapBytes(packet.len); -SwapBytes(packet.rnd); -#endif - -strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS)); -strncpy((char *)packet.type, "ALIVE_ACK", sizeof(packet.type)); - -return SendPacket(&packet, sizeof(packet), user); -} - -bool PROTO::Send_DISCONN_SYN(USER * user) -{ -DISCONN_SYN_8 packet; - -packet.len = sizeof(packet); - -#ifdef ARCH_BE -SwapBytes(packet.len); -#endif - -strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS)); -strncpy((char *)packet.type, "DISCONN_SYN", sizeof(packet.type)); -strncpy((char *)packet.login, user->GetLogin().c_str(), sizeof(packet.login)); - -return SendPacket(&packet, sizeof(packet), user); -} - -bool PROTO::Send_DISCONN_ACK(USER * user) -{ -DISCONN_ACK_8 packet; - -packet.len = sizeof(packet); -packet.rnd = user->IncRnd(); - -#ifdef ARCH_BE -SwapBytes(packet.len); -SwapBytes(packet.rnd); -#endif - -strncpy((char *)packet.loginS, user->GetLogin().c_str(), sizeof(packet.loginS)); -strncpy((char *)packet.type, "DISCONN_ACK", sizeof(packet.type)); - -return SendPacket(&packet, sizeof(packet), user); -} - -bool PROTO::SendPacket(const void * packet, size_t length, USER * user) -{ -HDR_8 hdr; - -assert(length < 2048 && "Packet length must not exceed 2048 bytes"); - -strncpy((char *)hdr.magic, IA_ID, sizeof(hdr.magic)); -hdr.protoVer[0] = 0; -hdr.protoVer[1] = 8; // IA_PROTO_VER - -unsigned char buffer[2048]; -memcpy(buffer, &hdr, sizeof(hdr)); -memcpy(buffer + sizeof(hdr), packet, length); - -size_t offset = sizeof(HDR_8); -for (size_t i = 0; i < IA_LOGIN_LEN / 8; i++) - { - Blowfish_Encrypt(&ctx, - (uint32_t *)(buffer + offset + i * 8), - (uint32_t *)(buffer + offset + i * 8 + 4)); - } - -offset += IA_LOGIN_LEN; -size_t encLen = (length - IA_LOGIN_LEN) / 8; -for (size_t i = 0; i < encLen; i++) - { - Blowfish_Encrypt(user->GetCtx(), - (uint32_t*)(buffer + offset + i * 8), - (uint32_t*)(buffer + offset + i * 8 + 4)); - } - -int res = sendto(user->GetSocket(), buffer, length, 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); - -if (res < 0) - { - errorStr = "Failed to send packet: '"; - errorStr += strerror(errno); - errorStr += "'"; - printfd(__FILE__, "PROTO::SendPacket() - %s, fd: %d\n", errorStr.c_str(), user->GetSocket()); - return false; - } - -if (res < length) - { - errorStr = "Packet sent partially"; - printfd(__FILE__, "PROTO::SendPacket() - %s\n", errorStr.c_str()); - return false; - } - -return true; -} - -bool PROTO::RealConnect(USER * user) -{ -if (user->GetPhase() != 1 && - user->GetPhase() != 5) - { - errorStr = "Unexpected connect"; - printfd(__FILE__, "PROTO::RealConnect() - wrong phase: %d\n", user->GetPhase()); - } -user->SetPhase(2); - -return Send_CONN_SYN(user); -} - -bool PROTO::RealDisconnect(USER * user) -{ -if (user->GetPhase() != 3) - { - errorStr = "Unexpected disconnect"; - printfd(__FILE__, "PROTO::RealDisconnect() - wrong phase: %d\n", user->GetPhase()); - } -user->SetPhase(4); - -return Send_DISCONN_SYN(user); -} diff --git a/projects/sgauthstress/proto.h b/projects/sgauthstress/proto.h deleted file mode 100644 index 746622b7..00000000 --- a/projects/sgauthstress/proto.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef __PROTO_H__ -#define __PROTO_H__ - -#ifndef LINUX -#include -#endif -#include -#include -#include - -#include -#include -#include -#include - -#include "stg/os_int.h" -#include "stg/blowfish.h" - -#include "user.h" - -class PROTO; - -typedef bool (PROTO::*PacketProcessor)(const void *, USER *); - -class PROTO { - public: - PROTO(const std::string & server, - uint16_t port, - uint16_t localPort, - int timeout = 1); - ~PROTO(); - - bool Start(); - bool Stop(); - - const std::string GetStrError() const { return errorStr; } - - void AddUser(const USER & user, bool connect = false); - - bool Connect(uint32_t ip); - bool Disconnect(uint32_t ip); - - size_t UserCount() const { return users.size(); } - private: - BLOWFISH_CTX ctx; - struct sockaddr_in localAddr; - struct sockaddr_in serverAddr; - int timeout; - - std::list > users; - std::vector pollFds; - - bool running; - bool stopped; - - pthread_t tid; - pthread_mutex_t mutex; - - std::string errorStr; - - std::map processors; - - static void * Runner(void * data); - - void Run(); - void CheckTimeouts(); - bool RecvPacket(); - bool SendPacket(const void * buffer, size_t length, USER * user); - bool HandlePacket(const char * buffer, size_t length, USER * user); - - bool CONN_SYN_ACK_Proc(const void * buffer, USER * user); - bool ALIVE_SYN_Proc(const void * buffer, USER * user); - bool DISCONN_SYN_ACK_Proc(const void * buffer, USER * user); - bool FIN_Proc(const void * buffer, USER * user); - bool INFO_Proc(const void * buffer, USER * user); - bool ERR_Proc(const void * buffer, USER * user); - - bool Send_CONN_SYN(USER * user); - bool Send_CONN_ACK(USER * user); - bool Send_DISCONN_SYN(USER * user); - bool Send_DISCONN_ACK(USER * user); - bool Send_ALIVE_ACK(USER * user); - - bool RealConnect(USER * user); - bool RealDisconnect(USER * user); -}; - -#endif diff --git a/projects/sgauthstress/rmifs.sh b/projects/sgauthstress/rmifs.sh deleted file mode 100755 index 0663b9d9..00000000 --- a/projects/sgauthstress/rmifs.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -users=`cat users.1000` -hi=0 -lo=0 -for user in $users -do - if (( $lo > 254 )) - then - lo=0 - let hi++ - fi - let lo++ - ip="10.22.$hi.$lo/32" - ip addr del $ip dev eth0 -done diff --git a/projects/sgauthstress/settings.cpp b/projects/sgauthstress/settings.cpp deleted file mode 100644 index 62adc143..00000000 --- a/projects/sgauthstress/settings.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#include -#include -#include - -#include "stg/dotconfpp.h" -#include "stg/module_settings.h" -#include "stg/common.h" - -#include "settings.h" - -SETTINGS::SETTINGS() - : port(0), - localPort(0), - confFile("sgauthstress.conf") -{ -} -//----------------------------------------------------------------------------- -int ParseModuleSettings(const DOTCONFDocumentNode * node, std::vector * params) -{ -assert(node && "DOTCONFDocumentNode must not be NULL!"); - -const DOTCONFDocumentNode * childNode = node->getChildNode(); -while (childNode) - { - PARAM_VALUE pv; - pv.param = childNode->getName(); - int i = 0; - const char * value; - while ((value = childNode->getValue(i++)) != NULL) - pv.value.push_back(value); - params->push_back(pv); - childNode = childNode->getNextNode(); - } - -return 0; -} -//----------------------------------------------------------------------------- -int SETTINGS::ReadSettings() -{ -const char * requiredOptions[] = { - "ModulesPath", - "StoreModule", - "Login", - "Password", - "ServerName", - "ServerPort", - NULL - }; - -DOTCONFDocument conf(DOTCONFDocument::CASEINSENSITIVE); -conf.setRequiredOptionNames(requiredOptions); - -if(conf.setContent(confFile.c_str()) != 0) - { - strError = "Cannot read file " + confFile + "."; - printfd(__FILE__, "SETTINGS::ReadSettings() - %s\n", strError.c_str()); - return -1; - } - -const DOTCONFDocumentNode * node = conf.getFirstNode(); - -int storeModulesCount = 0; -while (node) - { - if (strcasecmp(node->getName(), "ModulesPath") == 0) - modulesPath = node->getValue(0); - else if (strcasecmp(node->getName(), "Login") == 0) - login = node->getValue(0); - else if (strcasecmp(node->getName(), "Password") == 0) - password = node->getValue(0); - else if (strcasecmp(node->getName(), "ServerName") == 0) - serverName = node->getValue(0); - else if (strcasecmp(node->getName(), "ServerPort") == 0) - { - if (ParseIntInRange(node->getValue(0), 1, 65535, &port)) - { - strError = "Parameter 'ServerPort' is not valid."; - printfd(__FILE__, "SETTINGS::ReadSettings() - %s\n", strError.c_str()); - return -1; - } - } - else if (strcasecmp(node->getName(), "LocalPort") == 0) - { - if (ParseIntInRange(node->getValue(0), 0, 65535, &localPort)) - { - strError = "Parameter 'LocalPort' is not valid."; - printfd(__FILE__, "SETTINGS::ReadSettings() - %s\n", strError.c_str()); - return -1; - } - } - else if (strcasecmp(node->getName(), "StoreModule") == 0) - { - if (node->getValue(1)) - { - strError = "Unexpected \'" + std::string(node->getValue(1)) + "\'."; - printfd(__FILE__, "SETTINGS::ReadSettings() - %s\n", strError.c_str()); - return -1; - } - - if (storeModulesCount) - { - strError = "Should be only one source StoreModule."; - printfd(__FILE__, "SETTINGS::ReadSettings() - %s\n", strError.c_str()); - return -1; - } - ++storeModulesCount; - - storeModuleSettings.moduleName = node->getValue(0); - if (ParseModuleSettings(node, &storeModuleSettings.moduleParams)) - { - strError = "Failed to parse store module settings"; - printfd(__FILE__, "SETTINGS::ReadSettings() - %s\n", strError.c_str()); - return -1; - } - } - - node = node->getNextNode(); - } - -return 0; -} diff --git a/projects/sgauthstress/settings.h b/projects/sgauthstress/settings.h deleted file mode 100644 index 4e4b9be1..00000000 --- a/projects/sgauthstress/settings.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef SETTINGS_H -#define SETTINGS_H - -#include - -#include "stg/os_int.h" -#include "stg/module_settings.h" - -class DOTCONFDocumentNode; - -class SETTINGS { -public: - SETTINGS(); - ~SETTINGS() {} - int Reload() { return 0; } - void SetConfFile(const std::string & cf) { confFile = cf; } - int ReadSettings(); - - const std::string & GetStrError() const { return strError; } - - const std::string & GetServerName() const { return serverName; } - uint16_t GetServerPort() const { return port; } - uint16_t GetLocalPort() const { return localPort; } - - const std::string & GetLogin() const { return login; } - const std::string & GetPassword() const { return password; } - - const std::string & GetConfDir() const; - const std::string & GetModulesPath() const { return modulesPath; } - const MODULE_SETTINGS & GetStoreModuleSettings() const { return storeModuleSettings; } - -private: - std::string login; - std::string password; - std::string serverName; - int port; - int localPort; - - std::string confFile; - std::string strError; - std::string modulesPath; - - MODULE_SETTINGS storeModuleSettings; -}; - -#endif diff --git a/projects/sgauthstress/sgauthstress.conf b/projects/sgauthstress/sgauthstress.conf deleted file mode 100644 index e895c1d0..00000000 --- a/projects/sgauthstress/sgauthstress.conf +++ /dev/null @@ -1,34 +0,0 @@ -#Stargazer server ip -ServerName=10.21.5.4 - -#Stargazer server port -#Default value 5555 -ServerPort=5555 - -#User's login -Login=test - -# -# -LocalPort=12345 - -#User's password -Password=1234567 - -ModulesPath=../stargazer/modules - - - WorkDir = /var/stargazer - - ConfOwner = root - ConfGroup = root - ConfMode = 600 - - StatOwner = root - StatGroup = root - StatMode = 640 - - UserLogOwner = root - UserLogGroup = root - UserLogMode = 640 - diff --git a/projects/sgauthstress/store_loader.cpp b/projects/sgauthstress/store_loader.cpp deleted file mode 100644 index a545da35..00000000 --- a/projects/sgauthstress/store_loader.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -/* - $Revision: 1.6 $ - $Date: 2010/03/04 12:24:19 $ - $Author: faust $ - */ - -/* - * An implementation of RAII store plugin loader - */ - -#include - -#include "stg/common.h" -#include "stg/module_settings.h" -#include "stg/store.h" -#include "store_loader.h" - -STORE_LOADER::STORE_LOADER(const std::string & modulesPath, - const MODULE_SETTINGS & settings) - : isLoaded(false), - handle(NULL), - plugin(NULL), - errorStr(), - storeSettings(settings), - pluginFileName(modulesPath + "/mod_" + storeSettings.moduleName + ".so") -{ -} - -STORE_LOADER::~STORE_LOADER() -{ -Unload(); -} - -bool STORE_LOADER::Load() -{ -if (isLoaded) - { - errorStr = "Store plugin '" + pluginFileName + "' was already loaded!"; - printfd(__FILE__, "STORE_LOADER::Load() - %s\n", errorStr.c_str()); - return false; - } - -if (pluginFileName.empty()) - { - errorStr = "Empty store plugin filename"; - printfd(__FILE__, "STORE_LOADER::Load() - %s\n", errorStr.c_str()); - return true; - } - -handle = dlopen(pluginFileName.c_str(), RTLD_NOW); - -if (!handle) - { - errorStr = "Error loading plugin '" - + pluginFileName + "': '" + dlerror() + "'"; - printfd(__FILE__, "STORE_LOADER::Load() - %s\n", errorStr.c_str()); - return true; - } - -isLoaded = true; - -STORE * (*GetStore)(); -GetStore = (STORE * (*)())dlsym(handle, "GetStore"); -if (!GetStore) - { - errorStr = std::string("GetStore() not found! ") + dlerror(); - printfd(__FILE__, "STORE_LOADER::Load() - %s\n", errorStr.c_str()); - return true; - } - -plugin = GetStore(); - -if (!plugin) - { - errorStr = "Plugin was not created!"; - printfd(__FILE__, "STORE_LOADER::Load() - %s\n"); - return true; - } - -plugin->SetSettings(storeSettings); -if (plugin->ParseSettings()) - { - errorStr = plugin->GetStrError(); - printfd(__FILE__, "STORE_LOADER::Load() - Failed to parse settings. Plugin reports: '%s'\n", errorStr.c_str()); - return true; - } - -return false; -} - -bool STORE_LOADER::Unload() -{ -if (!isLoaded) - { - return true; - } - -printfd(__FILE__, "STORE_LOADER::Unload()\n"); - -if (dlclose(handle)) - { - errorStr = "Failed to unload plugin '"; - errorStr += pluginFileName + "': "; - errorStr += dlerror(); - printfd(__FILE__, "STORE_LOADER::Unload() - %s\n", errorStr.c_str()); - return true; - } - -isLoaded = false; - -return false; -} diff --git a/projects/sgauthstress/store_loader.h b/projects/sgauthstress/store_loader.h deleted file mode 100644 index 91d6e7cf..00000000 --- a/projects/sgauthstress/store_loader.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -/* - $Revision: 1.3 $ - $Date: 2010/03/04 12:24:19 $ - $Author: faust $ - */ - -/* - * Header file for RAII store plugin loader - */ - -#ifndef __STORE_LOADER_H__ -#define __STORE_LOADER_H__ - -#include - -#include "stg/module_settings.h" -#include "stg/noncopyable.h" - -class STORE; -class MODULE_SETTINGS; - -class STORE_LOADER : private NONCOPYABLE { -public: - STORE_LOADER(const std::string & modulesPath, - const MODULE_SETTINGS & settings); - ~STORE_LOADER(); - - bool Load(); - bool Unload(); - - STORE * GetStore() { return plugin; } - - const std::string & GetStrError() const { return errorStr; } -private: - bool isLoaded; - void * handle; - STORE * plugin; - std::string errorStr; - MODULE_SETTINGS storeSettings; - std::string pluginFileName; -}; - -#endif diff --git a/projects/sgauthstress/user.cpp b/projects/sgauthstress/user.cpp deleted file mode 100644 index 944907fe..00000000 --- a/projects/sgauthstress/user.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include // close - -#include -#include -#include - -#include "user.h" -#include "stg/ia_packets.h" -#include "stg/common.h" - -USER::USER(const std::string & l, - const std::string & pwd, - uint32_t i) - : login(l), - password(pwd), - ip(i), - aliveTimeout(5), - userTimeout(60), - phase(1), - phaseChangeTime(0), - rnd(0), - sock(-1) -{ -unsigned char key[IA_PASSWD_LEN]; -memset(key, 0, IA_PASSWD_LEN); -strncpy((char *)key, password.c_str(), IA_PASSWD_LEN); -Blowfish_Init(&ctx, key, IA_PASSWD_LEN); -} - -USER::USER(const USER & rvalue) - : login(rvalue.login), - password(rvalue.password), - ip(rvalue.ip), - aliveTimeout(rvalue.aliveTimeout), - userTimeout(rvalue.userTimeout), - phase(1), - phaseChangeTime(0), - rnd(0), - sock(-1) -{ -unsigned char key[IA_PASSWD_LEN]; -memset(key, 0, IA_PASSWD_LEN); -strncpy((char *)key, password.c_str(), IA_PASSWD_LEN); -Blowfish_Init(&ctx, key, IA_PASSWD_LEN); -} - -USER::~USER() -{ -if (sock > 0) - close(sock); -} - -USER & USER::operator=(const USER & rvalue) -{ -login = rvalue.login; -password = rvalue.password; -ip = rvalue.ip; -aliveTimeout = rvalue.aliveTimeout; -userTimeout = rvalue.userTimeout; -phase = 1; -phaseChangeTime = 0; -rnd = 0; -sock = -1; - -unsigned char key[IA_PASSWD_LEN]; -memset(key, 0, IA_PASSWD_LEN); -strncpy((char *)key, password.c_str(), IA_PASSWD_LEN); -Blowfish_Init(&ctx, key, IA_PASSWD_LEN); - -return *this; -} - -bool USER::InitNetwork() -{ -sock = socket(AF_INET, SOCK_DGRAM, 0); - -if (sock < 0) - { - throw std::runtime_error(std::string("USER::USER() - socket creation error: '") + strerror(errno) + "', ip: " + inet_ntostring(ip) + ", login: " + login); - } - -struct sockaddr_in addr; - -addr.sin_family = AF_INET; -addr.sin_addr.s_addr = ip; -addr.sin_port = htons(5554); // :( - -int res = bind(sock, (struct sockaddr *)&addr, sizeof(addr)); -if (res == -1) - { - throw std::runtime_error(std::string("USER::USER() - bind error: '") + strerror(errno) + "', ip: " + inet_ntostring(ip) + ", login: " + login); - } - -return true; -} diff --git a/projects/sgauthstress/user.h b/projects/sgauthstress/user.h deleted file mode 100644 index ef63a907..00000000 --- a/projects/sgauthstress/user.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __USER_H__ -#define __USER_H__ - -#include -#include - -#include "stg/os_int.h" -#include "stg/blowfish.h" - -class USER { - public: - USER(const std::string & login, - const std::string & password, - uint32_t ip); - USER(const USER & rvalue); - ~USER(); - - USER & operator=(const USER & rvalue); - - bool InitNetwork(); - - const std::string & GetLogin() const { return login; } - uint32_t GetIP() const { return ip; } - uint32_t GetAliveTimeout() const { return aliveTimeout; } - uint32_t GetUserTimeout() const { return userTimeout; } - int GetPhase() const { return phase; } - uint32_t GetRnd() const { return rnd; } - int GetSocket() const { return sock; } - time_t GetPhaseChangeTime() const { return phaseChangeTime; } - - BLOWFISH_CTX * GetCtx() { return &ctx; } - - void SetPhase(int p) { phase = p; time(&phaseChangeTime); } - void SetRnd(uint32_t r) { rnd = r; } - uint32_t IncRnd() { return ++rnd; } - void SetAliveTimeout(uint32_t timeout) { aliveTimeout = timeout; } - void SetUserTimeout(uint32_t timeout) { userTimeout = timeout; } - - private: - std::string login; - std::string password; - uint32_t ip; - uint32_t aliveTimeout; - uint32_t userTimeout; - int phase; - time_t phaseChangeTime; - uint32_t rnd; - int sock; - BLOWFISH_CTX ctx; -}; - -#endif diff --git a/projects/sgauthstress/users.1000 b/projects/sgauthstress/users.1000 deleted file mode 100644 index 36ff71e9..00000000 --- a/projects/sgauthstress/users.1000 +++ /dev/null @@ -1,1000 +0,0 @@ - -A -A's -AOL -AOL's -Aachen -Aachen's -Aaliyah -Aaliyah's -Aaron -Aaron's -Abbas -Abbasid -Abbasid's -Abbott -Abbott's -Abby -Abby's -Abdul -Abdul's -Abe -Abe's -Abel -Abel's -Abelard -Abelard's -Abelson -Abelson's -Aberdeen -Aberdeen's -Abernathy -Abernathy's -Abidjan -Abidjan's -Abigail -Abigail's -Abilene -Abilene's -Abner -Abner's -Abraham -Abraham's -Abram -Abram's -Abrams -Absalom -Absalom's -Abuja -Abyssinia -Abyssinia's -Abyssinian -Ac -Ac's -Acadia -Acadia's -Acapulco -Acapulco's -Accra -Accra's -Acevedo -Acevedo's -Achaean -Achaean's -Achebe -Achebe's -Achernar -Achernar's -Acheson -Acheson's -Achilles -Aconcagua -Aconcagua's -Acosta -Acosta's -Acropolis -Acropolis's -Acrux -Acrux's -Actaeon -Actaeon's -Acton -Acton's -Acts -Acuff -Acuff's -Ada -Ada's -Adam -Adam's -Adams -Adan -Adan's -Adana -Adana's -Adar -Adar's -Addams -Adderley -Adderley's -Addie -Addie's -Addison -Addison's -Adela -Adela's -Adelaide -Adelaide's -Adele -Adele's -Adeline -Adeline's -Aden -Aden's -Adenauer -Adenauer's -Adhara -Adhara's -Adidas -Adidas's -Adirondack -Adirondack's -Adirondacks -Adkins -Adkins's -Adler -Adler's -Adolf -Adolf's -Adolfo -Adolfo's -Adolph -Adolph's -Adonis -Adonis's -Adonises -Adrian -Adrian's -Adriana -Adriana's -Adriatic -Adrienne -Adrienne's -Advent -Advent's -Adventist -Adventist's -Advents -Advil -Advil's -Aegean -Aelfric -Aelfric's -Aeneas -Aeneid -Aeneid's -Aeolus -Aeolus's -Aeroflot -Aeroflot's -Aeschylus -Aeschylus's -Aesculapius -Aesculapius's -Aesop -Aesop's -Afghan -Afghan's -Afghanistan -Afghanistan's -Afghans -Africa -Africa's -African -Africans -Afrikaans -Afrikaans's -Afrikaner -Afrikaner's -Afrikaners -Afro -Afro's -Afrocentrism -Afros -Ag -Ag's -Agamemnon -Agamemnon's -Agassi -Agassi's -Agassiz -Agassiz's -Agatha -Agatha's -Aggie -Aggie's -Aglaia -Aglaia's -Agnes -Agnes's -Agnew -Agnew's -Agni -Agni's -Agra -Agra's -Agricola -Agricola's -Agrippa -Agrippa's -Agrippina -Agrippina's -Aguilar -Aguilar's -Aguinaldo -Aguinaldo's -Aguirre -Aguirre's -Agustin -Agustin's -Ahab -Ahab's -Ahmad -Ahmad's -Ahmadabad -Ahmed -Ahmed's -Ahriman -Ahriman's -Aida -Aida's -Aiken -Aiken's -Aileen -Aileen's -Aimee -Aimee's -Ainu -Ainu's -Airedale -Airedale's -Airedales -Aisha -Aisha's -Ajax -Ajax's -Akbar -Akbar's -Akhmatova -Akhmatova's -Akihito -Akihito's -Akita -Akita's -Akkad -Akkad's -Akron -Akron's -Al -Al's -Ala -Ala's -Alabama -Alabama's -Alabaman -Alabamans -Alabamian -Alabamians -Aladdin -Aladdin's -Alamo -Alamo's -Alamogordo -Alamogordo's -Alan -Alan's -Alana -Alana's -Alar -Alaric -Alaric's -Alaska -Alaska's -Alaskan -Alaskans -Alba -Alba's -Albania -Albania's -Albanian -Albanian's -Albanians -Albany -Albany's -Albee -Albee's -Alberio -Alberio's -Albert -Albert's -Alberta -Alberta's -Alberto -Alberto's -Albigensian -Albion -Albion's -Albireo -Albireo's -Albuquerque -Albuquerque's -Alcatraz -Alcatraz's -Alcestis -Alcestis's -Alcibiades -Alcibiades's -Alcmena -Alcmena's -Alcoa -Alcoa's -Alcott -Alcott's -Alcuin -Alcuin's -Alcyone -Alcyone's -Aldan -Aldan's -Aldebaran -Aldebaran's -Alden -Alden's -Alderamin -Alderamin's -Aldo -Aldo's -Aldrin -Aldrin's -Alec -Alec's -Aleichem -Aleichem's -Alejandra -Alejandra's -Alejandro -Alejandro's -Alembert -Alembert's -Aleppo -Aleppo's -Aleut -Aleut's -Aleutian -Alex -Alex's -Alexander -Alexander's -Alexandra -Alexandra's -Alexandria -Alexandria's -Alexei -Alexei's -Alexis -Alfonso -Alfonso's -Alfonzo -Alfonzo's -Alford -Alford's -Alfred -Alfred's -Alfreda -Alfreda's -Alfredo -Alfredo's -Algenib -Algenib's -Alger -Alger's -Algeria -Algeria's -Algerian -Algerians -Algieba -Algieba's -Algiers -Algiers's -Algol -Algol's -Algonquian -Algonquian's -Algonquians -Algonquin -Algonquin's -Alhambra -Alhambra's -Alhena -Alhena's -Ali -Ali's -Alice -Alice's -Alicia -Alicia's -Alighieri -Alighieri's -Aline -Aline's -Alioth -Alioth's -Alisa -Alisa's -Alisha -Alisha's -Alison -Alison's -Alissa -Alissa's -Alistair -Alistair's -Alkaid -Alkaid's -Allah -Allah's -Allahabad -Allahabad's -Allan -Allan's -Alleghenies -Allegheny -Allegheny's -Allegra -Allegra's -Allen -Allen's -Allende -Allende's -Allentown -Allentown's -Allie -Allie's -Allison -Allison's -Allstate -Allstate's -Allyson -Allyson's -Alma -Alma's -Almach -Almach's -Almaty -Almighty -Almighty's -Almohad -Almohad's -Almoravid -Almoravid's -Alnilam -Alnilam's -Alnitak -Alnitak's -Alonzo -Alonzo's -Alpert -Alpert's -Alphard -Alphard's -Alphecca -Alphecca's -Alpheratz -Alpheratz's -Alphonse -Alphonse's -Alphonso -Alphonso's -Alpine -Alpo -Alpo's -Alps -Alsace -Alsace's -Alsatian -Alsatian's -Alsop -Alsop's -Alston -Alston's -Alta -Alta's -Altai -Altai's -Altaic -Altaic's -Altair -Altair's -Altamira -Altamira's -Althea -Althea's -Altiplano -Altiplano's -Altman -Altman's -Altoids -Altoids's -Alton -Alton's -Aludra -Aludra's -Alva -Alva's -Alvarado -Alvarado's -Alvarez -Alvarez's -Alvaro -Alvaro's -Alvin -Alvin's -Alyce -Alyce's -Alyson -Alyson's -Alyssa -Alyssa's -Alzheimer -Alzheimer's -Am -Am's -Amadeus -Amadeus's -Amado -Amado's -Amalia -Amalia's -Amanda -Amanda's -Amarillo -Amarillo's -Amaru -Amaru's -Amaterasu -Amaterasu's -Amati -Amati's -Amazon -Amazon's -Amazons -Amber -Amber's -Amelia -Amelia's -Amenhotep -Amenhotep's -Amerasian -Amerasians -America -America's -American -Americana -Americana's -Americanism -Americanism's -Americanisms -Americanization -Americanization's -Americanizations -Americanize -Americanized -Americanizes -Americanizing -Americans -Americas -Amerind -Amerind's -Amerindian -Amerindian's -Amerindians -Amerinds -Ameslan -Ameslan's -Amharic -Amharic's -Amherst -Amherst's -Amie -Amie's -Amiga -Amiga's -Amish -Amman -Amman's -Amoco -Amoco's -Amos -Amparo -Amparo's -Ampere -Ampere's -Amritsar -Amritsar's -Amsterdam -Amsterdam's -Amtrak -Amundsen -Amundsen's -Amur -Amur's -Amway -Amway's -Amy -Amy's -Ana -Ana's -Anabaptist -Anabaptist's -Anabel -Anabel's -Anacin -Anacin's -Anacreon -Anacreon's -Anaheim -Anaheim's -Analects -Analects's -Ananias -Ananias's -Anasazi -Anasazi's -Anastasia -Anastasia's -Anatole -Anatole's -Anatolia -Anatolia's -Anatolian -Anaxagoras -Anaxagoras's -Anchorage -Anchorage's -Andalusia -Andalusia's -Andalusian -Andaman -Andean -Andersen -Andersen's -Anderson -Anderson's -Andes -Andorra -Andorra's -Andre -Andre's -Andrea -Andrea's -Andrei -Andrei's -Andres -Andrew -Andrew's -Andrews -Andrianampoinimerina -Andrianampoinimerina's -Andromache -Andromache's -Andromeda -Andromeda's -Andropov -Andy -Andy's -Angara -Angara's -Angel -Angel's -Angela -Angela's -Angelia -Angelia's -Angelica -Angelica's -Angelico -Angelico's -Angelina -Angelina's -Angeline -Angeline's -Angelique -Angelique's -Angelita -Angelita's -Angelo -Angelo's -Angelou -Angevin -Angevin's -Angie -Angie's -Angkor -Angkor's -Anglia -Anglia's -Anglican -Anglicanism -Anglicanism's -Anglicanisms -Anglicans -Anglicize -Anglicized -Anglicizes -Anglicizing -Anglo -Anglo's -Anglophile -Anglophile's -Anglophiles -Anglos -Angola -Angola's -Angolan -Angolans -Angora -Angora's -Angoras -Anguilla -Anguilla's -Angus -Angus's -Aniakchak -Aniakchak's -Anibal -Anibal's -Anita -Anita's -Ankara -Ankara's -Ann -Ann's -Anna -Anna's -Annabel -Annabel's -Annabelle -Annabelle's -Annam -Annam's -Annapolis -Annapolis's -Annapurna -Annapurna's -Anne -Anne's -Annette -Annette's -Annie -Annie's -Annmarie -Annmarie's -Anouilh -Anouilh's -Anselm -Anselm's -Anselmo -Anselmo's -Anshan -Anshan's -Antaeus -Antaeus's -Antananarivo -Antananarivo's -Antarctic -Antarctic's -Antarctica -Antarctica's -Antares -Anthony -Anthony's -Antichrist -Antichrist's -Antichrists -Antietam -Antietam's -Antigone -Antigone's -Antigua -Antigua's -Antilles -Antioch -Antioch's -Antipas -Antipas's -Antofagasta -Antofagasta's -Antoine -Antoine's -Antoinette -Antoinette's -Anton -Anton's -Antone -Antone's -Antonia -Antonia's -Antoninus -Antoninus's -Antonio -Antonio's -Antonius -Antonius's -Antony -Antony's -Antwan -Antwan's -Antwerp -Antwerp's -Anubis -Anubis's -Anzac -Anzac's -Apache -Apache's -Apaches -Apalachicola -Apalachicola's -Apennines -Aphrodite -Aphrodite's -Apia -Apia's -Apocrypha -Apocrypha's -Apollinaire -Apollinaire's -Apollo -Apollo's -Apollonian -Apollos -Appalachia -Appalachia's -Appalachian -Appalachians -Appaloosa -Appaloosa's -Apple -Apple's -Appleseed -Appleseed's -Appleton -Appleton's -Appomattox -Appomattox's -Apr -Apr's -April -April's -Aprils -Apuleius -Apuleius's -Aquafresh -Aquafresh's -Aquarius -Aquarius's -Aquariuses -Aquila -Aquila's -Aquinas -Aquinas's -Aquino -Aquino's -Aquitaine -Aquitaine's -Ar -Ar's -Ara -Ara's -Arab -Arab's -Arabia -Arabia's -Arabian -Arabians -Arabic -Arabic's -Arabs -Araby -Araby's -Araceli -Araceli's -Arafat -Arafat's -Araguaya -Araguaya's -Aral -Aral's -Aramaic -Aramaic's -Aramco -Aramco's -Arapaho -Arapaho's -Ararat -Ararat's -Araucanian -Araucanian's -Arawak -Arawak's -Arawakan -Arawakan's -Arbitron -Arbitron's -Arcadia -Arcadia's -Arcadian -Archean -Archibald -Archibald's -Archie -Archie's -Archimedes -Archimedes's -Arctic -Arctic's -Arcturus -Arcturus's -Arden -Arden's -Arequipa -Arequipa's -Ares -Argentina -Argentina's -Argentine -Argentine's -Argentines -Argentinian -Argentinians -Argo -Argo's -Argonaut -Argonaut's -Argonne -Argonne's -Argos -Argus -Argus's -Ariadne -Ariadne's -Arianism -Arianism's -Ariel -Ariel's -Aries -Arieses -Ariosto -Ariosto's -Aristarchus -Aristarchus's -Aristides -Aristophanes -Aristophanes's -Aristotelian -Aristotle -Aristotle's -Arius -Arius's -Ariz -Ariz's -Arizona -Arizona's -Arizonan -Arizonans -Arizonian -Arizonians -Arjuna -Arjuna's -Ark -Ark's -Arkansan -Arkansan's -Arkansas -Arkansas's -Arkhangelsk -Arkhangelsk's -Arkwright -Arkwright's -Arlene -Arlene's -Arline -Arline's -Arlington -Arlington's -Armageddon -Armageddon's -Armageddons -Armagnac -Armagnac's -Armand diff --git a/projects/sgconf/CHANGES b/projects/sgconf/CHANGES deleted file mode 100644 index e69de29b..00000000 diff --git a/projects/sgconf/Makefile b/projects/sgconf/Makefile deleted file mode 100644 index 3a64cb61..00000000 --- a/projects/sgconf/Makefile +++ /dev/null @@ -1,113 +0,0 @@ -############################################################################### -# $Id: Makefile,v 1.21 2010/02/11 12:34:14 faust Exp $ -############################################################################### - -include ../../Makefile.conf - -PROG = sgconf - -SRCS = ./main.cpp \ - ./options.cpp \ - ./api_action.cpp \ - ./actions.cpp \ - ./admins.cpp \ - ./tariffs.cpp \ - ./users.cpp \ - ./services.cpp \ - ./corps.cpp \ - ./info.cpp \ - ./xml.cpp - -STGLIBS = srvconf \ - crypto \ - common - -STGLIBS_INCS = $(addprefix -I ../../stglibs/,$(addsuffix .lib/include,$(STGLIBS))) -STGLIBS_LIBS = $(addprefix -L ../../stglibs/,$(addsuffix .lib,$(STGLIBS))) - -LIBS += $(addprefix -lstg,$(STGLIBS)) -lexpat $(LIB_THREAD) - -ifeq ($(OS),linux) -else -LIBS += -lc \ - -liconv -endif - -SEARCH_DIRS = -I ../../include - -ifeq ($(OS),bsd) -SEARCH_DIRS += -I/usr/local/include -CXXFLAGS += -DHAVE_DECL_GETOPT=1 -endif - -ifeq ($(OS),bsd5) -SEARCH_DIRS += -I/usr/local/include -CXXFLAGS += -DHAVE_DECL_GETOPT=1 -endif - -OBJS = $(notdir $(patsubst %.cpp, %.o, $(patsubst %.c, %.o, $(SRCS)))) - -CXXFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -CFLAGS += $(DEFS) $(STGLIBS_INCS) $(SEARCH_DIRS) -LDFLAGS += $(STGLIBS_LIBS) - -ifneq ($(OS),darwin) -LDFLAGS += -Wl,-E -endif - -.PHONY: all clean distclean libs install uninstall install-bin install-data uninstall-bin uninstall-data -all: libs $(PROG) ../../Makefile.conf - -libs: - $(MAKE) -C $(DIR_LIBSRC) - -$(PROG): $(OBJS) - $(CXX) $^ $(LDFLAGS) $(LIBS) -o $(PROG) - -clean: - rm -f deps $(PROG) *.o - $(MAKE) -C $(DIR_LIBSRC) clean - -distclean: clean - rm -f ../../Makefile.conf - -install: install-bin - -install-bin: -ifeq ($(DEBUG), yes) - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/sbin - install -m $(BIN_MODE) -o $(OWNER) $(PROG) $(PREFIX)/usr/sbin/$(PROG) -else - mkdir -m $(DIR_MODE) -p $(PREFIX)/usr/sbin - install -m $(BIN_MODE) -o $(OWNER) -s $(PROG) $(PREFIX)/usr/sbin/$(PROG) -endif - $(MAKE) -C $(DIR_LIBSRC) install - -uninstall: uninstall-bin - -uninstall-bin: - rm -f $(PREFIX)/usr/sbin/$(PROG) - - -ifneq ($(MAKECMDGOALS),distclean) -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(MAKECMDGOALS),uninstall) --include deps -endif -endif -endif - -deps: $(SRCS) ../../Makefile.conf - $(MAKE) -C $(DIR_LIBSRC) - @>deps ;\ - for file in $(SRCS); do\ - echo "$$file" | grep ".c$$" > /dev/null;\ - if [ $$? -eq 0 ];\ - then\ - echo "`$(CC) $(CFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CC) $(CFLAGS) -c $$<' >> deps ;\ - else\ - echo "`$(CXX) $(CXXFLAGS) -MM $$file` Makefile" >> deps ;\ - printf '%b\n' '\t$$(CXX) $(CXXFLAGS) -c $$<' >> deps ;\ - fi;\ - done diff --git a/projects/sgconf/README.txt b/projects/sgconf/README.txt deleted file mode 100644 index bb2db5b9..00000000 --- a/projects/sgconf/README.txt +++ /dev/null @@ -1,4 +0,0 @@ -Compiling: -> ./build - - diff --git a/projects/sgconf/TODO b/projects/sgconf/TODO deleted file mode 100644 index 19b51f5e..00000000 --- a/projects/sgconf/TODO +++ /dev/null @@ -1,2 +0,0 @@ -1. No default value for server. -2. No default value for port. diff --git a/projects/sgconf/action.h b/projects/sgconf/action.h deleted file mode 100644 index 940ea7f6..00000000 --- a/projects/sgconf/action.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef __STG_SGCONF_ACTION_H__ -#define __STG_SGCONF_ACTION_H__ - -#include -#include -#include - -namespace SGCONF -{ - -class OPTION_BLOCK; -struct PARSER_STATE; -struct CONFIG; - -class ACTION -{ - public: - virtual ~ACTION() {} - - virtual ACTION * Clone() const = 0; - virtual std::string ParamDescription() const = 0; - virtual std::string DefaultDescription() const = 0; - virtual OPTION_BLOCK & Suboptions() = 0; - virtual PARSER_STATE Parse(int argc, char ** argv, void * data = NULL) = 0; - virtual void ParseValue(const std::string &) {} - - class ERROR : public std::runtime_error - { - public: - ERROR(const std::string & message) - : std::runtime_error(message.c_str()) {} - }; -}; - -} // namespace SGCONF - -#endif diff --git a/projects/sgconf/actions.cpp b/projects/sgconf/actions.cpp deleted file mode 100644 index afa51621..00000000 --- a/projects/sgconf/actions.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ diff --git a/projects/sgconf/actions.h b/projects/sgconf/actions.h deleted file mode 100644 index 08dc177e..00000000 --- a/projects/sgconf/actions.h +++ /dev/null @@ -1,246 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef __STG_SGCONF_ACTIONS_H__ -#define __STG_SGCONF_ACTIONS_H__ - -#include "action.h" -#include "options.h" -#include "parser_state.h" - -#include "stg/common.h" -#include "stg/resetable.h" - -#include - -#include - -namespace SGCONF -{ - -typedef void (* FUNC0)(); - -template -class FUNC0_ACTION : public ACTION -{ - public: - FUNC0_ACTION(const F & func) : m_func(func) {} - - virtual ACTION * Clone() const { return new FUNC0_ACTION(*this); } - - virtual std::string ParamDescription() const { return ""; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/) - { - m_func(); - return PARSER_STATE(true, argc, argv); - } - - private: - F m_func; - OPTION_BLOCK m_suboptions; -}; - -template -inline -FUNC0_ACTION * MakeFunc0Action(F func) -{ -return new FUNC0_ACTION(func); -} - -template -class PARAM_ACTION : public ACTION -{ - public: - PARAM_ACTION(RESETABLE & param, - const T & defaultValue, - const std::string & paramDescription) - : m_param(param), - m_defaltValue(defaultValue), - m_description(paramDescription), - m_hasDefault(true) - {} - PARAM_ACTION(RESETABLE & param) - : m_param(param), - m_hasDefault(false) - {} - PARAM_ACTION(RESETABLE & param, - const std::string & paramDescription) - : m_param(param), - m_description(paramDescription), - m_hasDefault(false) - {} - - virtual ACTION * Clone() const { return new PARAM_ACTION(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const; - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); - virtual void ParseValue(const std::string & value); - - private: - RESETABLE & m_param; - T m_defaltValue; - std::string m_description; - bool m_hasDefault; - OPTION_BLOCK m_suboptions; -}; - -template -inline -std::string PARAM_ACTION::DefaultDescription() const -{ -return m_hasDefault ? " (default: '" + x2str(m_defaltValue) + "')" - : ""; -} - -template <> -inline -std::string PARAM_ACTION::DefaultDescription() const -{ -return m_hasDefault ? " (default: '" + m_defaltValue + "')" - : ""; -} - -template -inline -PARSER_STATE PARAM_ACTION::Parse(int argc, char ** argv, void * /*data*/) -{ -if (argc == 0 || - argv == NULL || - *argv == NULL) - throw ERROR("Missing argument."); -T value; -if (str2x(*argv, value)) - throw ERROR(std::string("Bad argument: '") + *argv + "'"); -m_param = value; -return PARSER_STATE(false, --argc, ++argv); -} - -template <> -inline -PARSER_STATE PARAM_ACTION::Parse(int argc, char ** argv, void * /*data*/) -{ -m_param = true; -return PARSER_STATE(false, argc, argv); -} - -template -inline -void PARAM_ACTION::ParseValue(const std::string & stringValue) -{ -if (stringValue.empty()) - throw ERROR("Missing value."); -T value; -if (str2x(stringValue, value)) - throw ERROR(std::string("Bad value: '") + stringValue + "'"); -m_param = value; -} - -template <> -inline -void PARAM_ACTION::ParseValue(const std::string & stringValue) -{ -m_param = stringValue; -} - -template <> -inline -PARSER_STATE PARAM_ACTION::Parse(int argc, char ** argv, void * /*data*/) -{ -if (argc == 0 || - argv == NULL || - *argv == NULL) - throw ERROR("Missing argument."); -m_param = *argv; -return PARSER_STATE(false, --argc, ++argv); -} - -template -inline -PARAM_ACTION * MakeParamAction(RESETABLE & param, - const T & defaultValue, - const std::string & paramDescription) -{ -return new PARAM_ACTION(param, defaultValue, paramDescription); -} - -template -inline -PARAM_ACTION * MakeParamAction(RESETABLE & param) -{ -return new PARAM_ACTION(param); -} - -template -inline -PARAM_ACTION * MakeParamAction(RESETABLE & param, - const std::string & paramDescription) -{ -return new PARAM_ACTION(param, paramDescription); -} - -class KV_ACTION : public ACTION -{ - public: - KV_ACTION(const std::string & name, - const std::string & paramDescription) - : m_name(name), - m_description(paramDescription) - {} - - virtual ACTION * Clone() const { return new KV_ACTION(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * data); - - private: - std::string m_name; - std::string m_description; - OPTION_BLOCK m_suboptions; -}; - -inline -PARSER_STATE KV_ACTION::Parse(int argc, char ** argv, void * data) -{ -if (argc == 0 || - argv == NULL || - *argv == NULL) - throw ERROR("Missing argument."); -assert(data != NULL && "Expecting container pointer."); -std::map & kvs = *static_cast*>(data); -kvs[m_name] = *argv; -return PARSER_STATE(false, --argc, ++argv); -} - -inline -KV_ACTION * MakeKVAction(const std::string & name, - const std::string & paramDescription) -{ -return new KV_ACTION(name, paramDescription); -} - -} // namespace SGCONF - -#endif diff --git a/projects/sgconf/admins.cpp b/projects/sgconf/admins.cpp deleted file mode 100644 index c16e6e2b..00000000 --- a/projects/sgconf/admins.cpp +++ /dev/null @@ -1,204 +0,0 @@ -#include "admins.h" - -#include "api_action.h" -#include "options.h" -#include "config.h" -#include "utils.h" - -#include "stg/servconf.h" -#include "stg/servconf_types.h" -#include "stg/os_int.h" - -#include -#include -#include -#include - -namespace -{ - -std::string Indent(size_t level, bool dash = false) -{ -if (level == 0) - return ""; -return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' '); -} - -std::string PrivToString(const PRIV& priv) -{ -return std::string("") + - (priv.corpChg ? "1" : "0") + - (priv.serviceChg ? "1" : "0") + - (priv.tariffChg ? "1" : "0") + - (priv.adminChg ? "1" : "0") + - (priv.userAddDel ? "1" : "0") + - (priv.userPasswd ? "1" : "0") + - (priv.userCash ? "1" : "0") + - (priv.userConf ? "1" : "0") + - (priv.userStat ? "1" : "0"); -} - -void PrintAdmin(const STG::GET_ADMIN::INFO & info, size_t level = 0) -{ -std::cout << Indent(level, true) << "login: " << info.login << "\n" - << Indent(level) << "priviledges: " << PrivToString(info.priv) << "\n"; -} - -std::vector GetAdminParams() -{ -std::vector params; -params.push_back(SGCONF::API_ACTION::PARAM("password", "", "password")); -params.push_back(SGCONF::API_ACTION::PARAM("priv", "", "priviledges")); -return params; -} - -void ConvPriv(const std::string & value, RESETABLE & res) -{ -if (value.length() != 9) - throw SGCONF::ACTION::ERROR("Priviledges value should be a 9-digits length binary number."); -PRIV priv; -priv.corpChg = (value[0] == '0' ? 0 : 1); -priv.serviceChg = (value[1] == '0' ? 0 : 1); -priv.tariffChg = (value[2] == '0' ? 0 : 1); -priv.adminChg = (value[3] == '0' ? 0 : 1); -priv.userAddDel = (value[4] == '0' ? 0 : 1); -priv.userPasswd = (value[5] == '0' ? 0 : 1); -priv.userCash = (value[6] == '0' ? 0 : 1); -priv.userConf = (value[7] == '0' ? 0 : 1); -priv.userStat = (value[8] == '0' ? 0 : 1); -res = priv; -} - -void SimpleCallback(bool result, - const std::string & reason, - void * /*data*/) -{ -if (!result) - { - std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl; - return; - } -std::cout << "Success.\n"; -} - -void GetAdminsCallback(bool result, - const std::string & reason, - const std::vector & info, - void * /*data*/) -{ -if (!result) - { - std::cerr << "Failed to get admin list. Reason: '" << reason << "'." << std::endl; - return; - } -std::cout << "Admins:\n"; -for (size_t i = 0; i < info.size(); ++i) - PrintAdmin(info[i], 1); -} - -void GetAdminCallback(bool result, - const std::string & reason, - const std::vector & info, - void * data) -{ -assert(data != NULL && "Expecting pointer to std::string with the admin's login."); -const std::string & login = *static_cast(data); -if (!result) - { - std::cerr << "Failed to get admin. Reason: '" << reason << "'." << std::endl; - return; - } -for (size_t i = 0; i < info.size(); ++i) - if (info[i].login == login) - PrintAdmin(info[i]); -} - - -bool GetAdminsFunction(const SGCONF::CONFIG & config, - const std::string & /*arg*/, - const std::map & /*options*/) -{ -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.GetAdmins(GetAdminsCallback, NULL) == STG::st_ok; -} - -bool GetAdminFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & /*options*/) -{ -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -// STG currently doesn't support . -// So get a list of admins and filter it. 'data' param holds a pointer to 'login'. -std::string login(arg); -return proto.GetAdmins(GetAdminCallback, &login) == STG::st_ok; -} - -bool DelAdminFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & /*options*/) -{ -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.DelAdmin(arg, SimpleCallback, NULL) == STG::st_ok; -} - -bool AddAdminFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & options) -{ -ADMIN_CONF_RES conf; -conf.login = arg; -SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv); -SGCONF::MaybeSet(options, "password", conf.password); -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.AddAdmin(arg, conf, SimpleCallback, NULL) == STG::st_ok; -} - -bool ChgAdminFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & options) -{ -ADMIN_CONF_RES conf; -conf.login = arg; -SGCONF::MaybeSet(options, "priv", conf.priv, ConvPriv); -SGCONF::MaybeSet(options, "password", conf.password); -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.ChgAdmin(conf, SimpleCallback, NULL) == STG::st_ok; -} - -} // namespace anonymous - -void SGCONF::AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks) -{ -std::vector params(GetAdminParams()); -blocks.Add("Admin management options") - .Add("get-admins", SGCONF::MakeAPIAction(commands, GetAdminsFunction), "\tget admin list") - .Add("get-admin", SGCONF::MakeAPIAction(commands, "", GetAdminFunction), "get admin") - .Add("add-admin", SGCONF::MakeAPIAction(commands, "", params, AddAdminFunction), "add admin") - .Add("del-admin", SGCONF::MakeAPIAction(commands, "", DelAdminFunction), "del admin") - .Add("chg-admin", SGCONF::MakeAPIAction(commands, "", params, ChgAdminFunction), "change admin"); -} diff --git a/projects/sgconf/admins.h b/projects/sgconf/admins.h deleted file mode 100644 index 6bc47380..00000000 --- a/projects/sgconf/admins.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __STG_SGCONF_ADMINS_H__ -#define __STG_SGCONF_ADMINS_H__ - -namespace SGCONF -{ - -class OPTION_BLOCKS; -class COMMANDS; - -void AppendAdminsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks); - -} // namespace SGCONF - -#endif diff --git a/projects/sgconf/api_action.cpp b/projects/sgconf/api_action.cpp deleted file mode 100644 index d5b1e8e6..00000000 --- a/projects/sgconf/api_action.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "api_action.h" - -#include "actions.h" -#include "parser_state.h" - -SGCONF::PARSER_STATE SGCONF::API_ACTION::Parse(int argc, char ** argv, void * /*data*/) -{ -PARSER_STATE state(false, argc, argv); -if (!m_argument.empty()) - { - if (argc == 0 || - argv == NULL || - *argv == NULL) - throw ERROR("Missing argument."); - m_argument = *argv; - --state.argc; - ++state.argv; - } -state = m_suboptions.Parse(state.argc, state.argv, &m_params); -m_commands.Add(m_funPtr, m_argument, m_params); -return state; -} - -SGCONF::API_ACTION::API_ACTION(COMMANDS & commands, - const std::string & paramDescription, - bool needArgument, - const std::vector & params, - API_FUNCTION funPtr) - : m_commands(commands), - m_description(paramDescription), - m_argument(needArgument ? "1" : ""), // Hack - m_funPtr(funPtr) -{ -std::vector::const_iterator it(params.begin()); -while (it != params.end()) - { - m_suboptions.Add(it->name, MakeKVAction(it->name, it->shortDescr), it->longDescr); - ++it; - } -} diff --git a/projects/sgconf/api_action.h b/projects/sgconf/api_action.h deleted file mode 100644 index f27715ca..00000000 --- a/projects/sgconf/api_action.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef __STG_SGCONF_API_ACTION_H__ -#define __STG_SGCONF_API_ACTION_H__ - -#include "action.h" - -#include "options.h" - -#include -#include -#include - -namespace SGCONF -{ - -typedef bool (* API_FUNCTION) (const CONFIG &, - const std::string &, - const std::map &); - -class COMMAND -{ - public: - COMMAND(API_FUNCTION funPtr, - const std::string & arg, - const std::map & options) - : m_funPtr(funPtr), - m_arg(arg), - m_options(options) - {} - bool Execute(const SGCONF::CONFIG & config) const - { - return m_funPtr(config, m_arg, m_options); - } - - private: - API_FUNCTION m_funPtr; - std::string m_arg; - std::map m_options; -}; - -class COMMANDS -{ - public: - void Add(API_FUNCTION funPtr, - const std::string & arg, - const std::map & options) { m_commands.push_back(COMMAND(funPtr, arg, options)); } - bool Execute(const SGCONF::CONFIG & config) const - { - std::vector::const_iterator it(m_commands.begin()); - bool res = true; - while (it != m_commands.end() && res) - { - res = res && it->Execute(config); - ++it; - } - return res; - } - private: - std::vector m_commands; -}; - -class API_ACTION : public ACTION -{ - public: - struct PARAM - { - PARAM(const std::string & n, - const std::string & s, - const std::string & l) - : name(n), - shortDescr(s), - longDescr(l) - {} - std::string name; - std::string shortDescr; - std::string longDescr; - }; - - API_ACTION(COMMANDS & commands, - const std::string & paramDescription, - bool needArgument, - const std::vector & params, - API_FUNCTION funPtr); - API_ACTION(COMMANDS & commands, - const std::string & paramDescription, - bool needArgument, - API_FUNCTION funPtr) - : m_commands(commands), - m_description(paramDescription), - m_argument(needArgument ? "1" : ""), // Hack - m_funPtr(funPtr) - {} - - virtual ACTION * Clone() const { return new API_ACTION(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); - - private: - COMMANDS & m_commands; - std::string m_description; - std::string m_argument; - OPTION_BLOCK m_suboptions; - std::map m_params; - API_FUNCTION m_funPtr; -}; - -inline -ACTION * MakeAPIAction(COMMANDS & commands, - const std::string & paramDescription, - const std::vector & params, - API_FUNCTION funPtr) -{ -return new API_ACTION(commands, paramDescription, true, params, funPtr); -} - -inline -ACTION * MakeAPIAction(COMMANDS & commands, - const std::vector & params, - API_FUNCTION funPtr) -{ -return new API_ACTION(commands, "", false, params, funPtr); -} - -inline -ACTION * MakeAPIAction(COMMANDS & commands, - const std::string & paramDescription, - API_FUNCTION funPtr) -{ -return new API_ACTION(commands, paramDescription, true, funPtr); -} - -inline -ACTION * MakeAPIAction(COMMANDS & commands, - API_FUNCTION funPtr) -{ -return new API_ACTION(commands, "", false, funPtr); -} - -} - -#endif diff --git a/projects/sgconf/build b/projects/sgconf/build deleted file mode 100755 index 7ac18e3c..00000000 --- a/projects/sgconf/build +++ /dev/null @@ -1,225 +0,0 @@ -#!/bin/sh - -# $Author: faust $ -# $Revision: 1.21 $ -# $Date: 2010/04/14 08:59:11 $ -###################################################### - -OS=unknown -sys=`uname -s` -release=`uname -r` -major=`printf "%s" "$release" | cut -d. -f1` -BUILD_DIR=`pwd` -CONFFILE="../../Makefile.conf" -PREFIX="/" -BIN_MODE=0755 -DATA_MODE=0644 -DIR_MODE=0755 -OWNER=root - -if [ "$1" = "debug" ] -then - DEFS="$DEFS -DDEBUG" - MAKEOPTS="$MAKEOPTS -j1" - CFLAGS="$CFLAGS -ggdb3 -W -Wall -Wextra" - CXXFLAGS="$CXXFLAGS -ggdb3 -W -Wall -Wextra" - DEBUG="yes" -else - DEFS="$DEFS -DNDEBUG" - DEBUG="no" -fi - -CFLAGS="$CFLAGS -I/usr/local/include" -CXXFLAGS="$CXXFLAGS -I/usr/local/include" -LDFLAGS="$LDFLAGS -L/usr/local/lib" - -if [ "$sys" = "Linux" ] -then - OS=linux - MAKE="make" -fi - -if [ "$sys" = "FreeBSD" ] -then - case $major in - 4) OS=bsd;; - 5) OS=bsd5;; - 6) OS=bsd5;; - 7) OS=bsd7;; - *) OS=bsd7;; - esac - MAKE="gmake" -fi - -if [ "$sys" = "Darwin" ] -then - OS=darwin - ETC_DIR="./inst/freebsd/etc/stargazer" - MAKE="gmake" -fi - -if [ "$OS" = "unknown" ] -then - printf "#############################################################################\n" - printf "# Sorry, but sgconf is currently supported by Linux, FreeBSD and Darwin. #\n" - printf "#############################################################################\n" - exit 1 -fi - -printf "#############################################################################\n" -printf " Building sgconf for $sys $release\n" -printf "#############################################################################\n" - -STG_LIBS="conffiles.lib - crypto.lib - common.lib - srvconf.lib" - -if [ "$OS" = "linux" ] -then - DEFS="$DEFS -DLINUX" - LIB_THREAD=-lpthread -else - LIBICONV="-liconv" - if [ "$OS" = "bsd" ] - then - DEFS="$DEFS -DFREE_BSD" - else - if [ "$OS" = "bsd7" ] - then - DEFS="$DEFS -DFREE_BSD5" - LIB_THREAD=-lpthread - else - if [ "$OS" == "darwin" ] - then - DEFS="$DEFS -DDARWIN" - LIB_THREAD=-lpthread - else - LIB_THREAD=-lc_r - fi - fi - fi -fi - -if [ -z "$CC" ] -then - CC=gcc -fi - -if [ -z "$CXX" ] -then - CXX=g++ -fi - -printf "Checking CC... " -$CC --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CC not found\n" - exit; -fi -printf "found\n" -printf "Checking CXX... " -$CXX --version > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "$CXX not found\n" - exit; -fi -printf "found\n" - -printf "Checking endianess... " -printf "int main() { int probe = 0x00000001; return *(char *)&probe; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "FAIL!\n" - printf "Endianess checking failed\n" - exit; -else - ./fake - if [ $? = 1 ] - then - ARCH=le - CXXFLAGS="$CXXFLAGS -DARCH_LE" - CFLAGS="$CFLAGS -DARCH_LE" - printf "Little Endian\n" - else - ARCH=be - CXXFLAGS="$CXXFLAGS -DARCH_BE" - CFLAGS="$CFLAGS -DARCH_BE" - printf "Big Endian\n" - fi -fi -rm -f fake - -printf "Checking for -lexpat... " -printf "int main() { return 0; }\n" > build_check.c -$CC $CFLAGS $LDFLAGS build_check.c -lexpat -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - CHECK_EXPAT=no - printf "no\n" -else - CHECK_EXPAT=yes - printf "yes\n" -fi -rm -f fake - -printf "Checking for iconv 2nd argument... " -printf "#include \nint main(){ const char** src = 0; iconv(0, src, 0, 0, 0); }\n" > build_check.c -$CC $CFLAGS $LDFLAGS -Werror build_check.c $LIBICONV -o fake > /dev/null 2> /dev/null -if [ $? != 0 ] -then - printf "non-const\n" -else - DEFS="$DEFS -DCONST_ICONV" - printf "const\n" -fi -rm -f fake - -rm -f build_check.c - -if [ "$CHECK_EXPAT" != "yes" ] -then - printf "-lexpat not found!\n" - exit 1 -fi - -printf "OS=$OS\n" > $CONFFILE -printf "STG_TIME=yes\n" >> $CONFFILE -printf "DEBUG=$DEBUG\n" >> $CONFFILE -printf "DIR_BUILD=$BUILD_DIR\n" >> $CONFFILE -printf "DIR_LIB=\$(DIR_BUILD)/../../lib\n" >> $CONFFILE -printf "DIR_LIBSRC=\$(DIR_BUILD)/../../stglibs\n" >> $CONFFILE -printf "DIR_INCLUDE=\$(DIR_BUILD)/../../include\n" >> $CONFFILE -printf "ARCH=$ARCH\n" >> $CONFFILE -printf "CHECK_EXPAT=$CHECK_EXPAT\n" >> $CONFFILE -printf "DEFS=$DEFS\n" >> $CONFFILE -printf "STG_LIBS=" >> $CONFFILE -for lib in $STG_LIBS -do - printf "$lib " >> $CONFFILE -done -printf "\n" >> $CONFFILE -printf "LIB_THREAD=$LIB_THREAD\n" >> $CONFFILE -printf "CC=$CC\n" >> $CONFFILE -printf "CXX=$CXX\n" >> $CONFFILE -printf "CXXFLAGS=$CXXFLAGS\n" >> $CONFFILE -printf "CFLAGS=$CFLAGS\n" >> $CONFFILE -printf "LDFLAGS=$LDFLAGS\n" >> $CONFFILE -printf "LIBICONV=$LIBICONV\n" >> $CONFFILE -printf "PREFIX=$PREFIX\n" >> $CONFFILE -printf "BIN_MODE=$BIN_MODE\n" >> $CONFFILE -printf "DATA_MODE=$DATA_MODE\n" >> $CONFFILE -printf "DIR_MODE=$DIR_MODE\n" >> $CONFFILE -printf "OWNER=$OWNER\n" >> $CONFFILE - -if [ "$1" != "debug" ] -then - $MAKE $MAKEOPTS -else - printf "\n\n\nDebug build. Type $MAKE explicitly\n" -fi diff --git a/projects/sgconf/config.h b/projects/sgconf/config.h deleted file mode 100644 index d3659a1d..00000000 --- a/projects/sgconf/config.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef __STG_SGCONF_CONFIG_H__ -#define __STG_SGCONF_CONFIG_H__ - -#include "stg/common.h" -#include "stg/resetable.h" -#include "stg/os_int.h" - -#include - -namespace SGCONF -{ - -struct CONFIG -{ - RESETABLE configFile; - RESETABLE server; - RESETABLE port; - RESETABLE localAddress; - RESETABLE localPort; - RESETABLE userName; - RESETABLE userPass; - RESETABLE showConfig; - - CONFIG & operator=(const CONFIG & rhs) - { - if (!rhs.configFile.empty()) - configFile = rhs.configFile; - if (!rhs.server.empty()) - server = rhs.server; - if (!rhs.port.empty()) - port = rhs.port; - if (!rhs.localAddress.empty()) - localAddress = rhs.localAddress; - if (!rhs.localPort.empty()) - localPort = rhs.localPort; - if (!rhs.userName.empty()) - userName = rhs.userName; - if (!rhs.userPass.empty()) - userPass = rhs.userPass; - if (!rhs.showConfig.empty()) - showConfig = rhs.showConfig; - return *this; - } - - std::string Serialize() const - { - std::string res; - if (!configFile.empty()) - res += "configFile: '" + configFile.data() + "'\n"; - if (!server.empty()) - res += "server: '" + server.data() + "'\n"; - if (!port.empty()) - res += "port: " + x2str(port.data()) + "\n"; - if (!localAddress.empty()) - res += "local address: '" + localAddress.data() + "'\n"; - if (!localPort.empty()) - res += "local port: " + x2str(localPort.data()) + "\n"; - if (!userName.empty()) - res += "userName: '" + userName.data() + "'\n"; - if (!userPass.empty()) - res += "userPass: '" + userPass.data() + "\n"; - return res; - } -}; - -} // namespace SGCONF - -#endif diff --git a/projects/sgconf/corps.cpp b/projects/sgconf/corps.cpp deleted file mode 100644 index 4bd436dd..00000000 --- a/projects/sgconf/corps.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "corps.h" - -#include "api_action.h" -#include "options.h" -#include "config.h" -#include "utils.h" - -#include "stg/servconf.h" -#include "stg/servconf_types.h" -#include "stg/corp_conf.h" -#include "stg/common.h" - -#include -#include -#include - -namespace -{ - -std::string Indent(size_t level, bool dash = false) -{ -if (level == 0) - return ""; -return dash ? std::string(level * 4 - 2, ' ') + "- " : std::string(level * 4, ' '); -} - -void PrintCorp(const STG::GET_CORP::INFO & info, size_t level = 0) -{ -std::cout << Indent(level, true) << "name: " << info.name << "\n" - << Indent(level) << "cash: " << info.cash << "\n"; -} - -std::vector GetCorpParams() -{ -std::vector params; -params.push_back(SGCONF::API_ACTION::PARAM("cash", "", "\tcorporation's cash")); -return params; -} - -void SimpleCallback(bool result, - const std::string & reason, - void * /*data*/) -{ -if (!result) - { - std::cerr << "Operation failed. Reason: '" << reason << "'." << std::endl; - return; - } -std::cout << "Success.\n"; -} - -void GetCorpsCallback(bool result, - const std::string & reason, - const std::vector & info, - void * /*data*/) -{ -if (!result) - { - std::cerr << "Failed to get corp list. Reason: '" << reason << "'." << std::endl; - return; - } -std::cout << "Corps:\n"; -for (size_t i = 0; i < info.size(); ++i) - PrintCorp(info[i], 1); -} - -void GetCorpCallback(bool result, - const std::string & reason, - const STG::GET_CORP::INFO & info, - void * /*data*/) -{ -if (!result) - { - std::cerr << "Failed to get corp. Reason: '" << reason << "'." << std::endl; - return; - } -PrintCorp(info); -} - -bool GetCorpsFunction(const SGCONF::CONFIG & config, - const std::string & /*arg*/, - const std::map & /*options*/) -{ -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.GetCorporations(GetCorpsCallback, NULL) == STG::st_ok; -} - -bool GetCorpFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & /*options*/) -{ -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.GetCorp(arg, GetCorpCallback, NULL) == STG::st_ok; -} - -bool DelCorpFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & /*options*/) -{ -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.DelCorp(arg, SimpleCallback, NULL) == STG::st_ok; -} - -bool AddCorpFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & options) -{ -CORP_CONF_RES conf; -conf.name = arg; -SGCONF::MaybeSet(options, "cash", conf.cash); -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.AddCorp(arg, conf, SimpleCallback, NULL) == STG::st_ok; -} - -bool ChgCorpFunction(const SGCONF::CONFIG & config, - const std::string & arg, - const std::map & options) -{ -CORP_CONF_RES conf; -conf.name = arg; -SGCONF::MaybeSet(options, "cash", conf.cash); -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.ChgCorp(conf, SimpleCallback, NULL) == STG::st_ok; -} - -} // namespace anonymous - -void SGCONF::AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks) -{ -std::vector params(GetCorpParams()); -blocks.Add("Corporation management options") - .Add("get-corps", SGCONF::MakeAPIAction(commands, GetCorpsFunction), "\tget corporation list") - .Add("get-corp", SGCONF::MakeAPIAction(commands, "", GetCorpFunction), "get corporation") - .Add("add-corp", SGCONF::MakeAPIAction(commands, "", params, AddCorpFunction), "add corporation") - .Add("del-corp", SGCONF::MakeAPIAction(commands, "", DelCorpFunction), "delete corporation") - .Add("chg-corp", SGCONF::MakeAPIAction(commands, "", params, ChgCorpFunction), "change corporation"); -} diff --git a/projects/sgconf/corps.h b/projects/sgconf/corps.h deleted file mode 100644 index de823b7b..00000000 --- a/projects/sgconf/corps.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef __STG_SGCONF_CORPS_H__ -#define __STG_SGCONF_CORPS_H__ - -namespace SGCONF -{ - -class OPTION_BLOCKS; -class COMMANDS; - -void AppendCorpsOptionBlock(COMMANDS & commands, OPTION_BLOCKS & blocks); - -} // namespace SGCONF - -#endif diff --git a/projects/sgconf/info.cpp b/projects/sgconf/info.cpp deleted file mode 100644 index 0e98d3dc..00000000 --- a/projects/sgconf/info.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "info.h" - -#include "api_action.h" -#include "options.h" -#include "config.h" - -#include "stg/servconf.h" - -#include -#include -#include - -#include - -namespace -{ - -void PrintInfo(const STG::SERVER_INFO::INFO& info) -{ - std::cout << "Server version: '" << info.version << "'\n" - << "Number of tariffs: " << info.tariffNum << "\n" - << "Tariff subsystem version: " << info.tariffType << "\n" - << "Number of users: " << info.usersNum << "\n" - << "UName: '" << info.uname << "\n" - << "Number of directions: " << info.dirNum << "\n" - << "Dirs:\n"; - for (size_t i = 0; i < info.dirName.size(); ++i) - std::cout << "\t - '" << info.dirName[i] << "'\n"; -} - -void InfoCallback(bool result, const std::string & reason, const STG::SERVER_INFO::INFO & info, void * /*data*/) -{ -if (!result) - { - std::cerr << "Failed to get server info. Reason: '" << reason << "'." << std::endl; - return; - } -PrintInfo(info); -} - -bool InfoFunction(const SGCONF::CONFIG & config, - const std::string& /*arg*/, - const std::map & /*options*/) -{ -STG::SERVCONF proto(config.server.data(), - config.port.data(), - config.localAddress.data(), - config.localPort.data(), - config.userName.data(), - config.userPass.data()); -return proto.ServerInfo(InfoCallback, NULL) == STG::st_ok; -} - -} - -void SGCONF::AppendServerInfoBlock(COMMANDS & commands, OPTION_BLOCKS & blocks) -{ -blocks.Add("Server info") - .Add("server-info", SGCONF::MakeAPIAction(commands, InfoFunction), "\tget server info"); -} diff --git a/projects/sgconf/info.h b/projects/sgconf/info.h deleted file mode 100644 index 86e4a9ec..00000000 --- a/projects/sgconf/info.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Maxim Mamontov - */ - -#ifndef __STG_SGCONF_SERVER_INFO_H__ -#define __STG_SGCONF_SERVER_INFO_H__ - -namespace SGCONF -{ - -class OPTION_BLOCKS; -class COMMANDS; - -void AppendServerInfoBlock(COMMANDS & commands, OPTION_BLOCKS & blocks); - -} - -#endif diff --git a/projects/sgconf/main.cpp b/projects/sgconf/main.cpp deleted file mode 100644 index 97908195..00000000 --- a/projects/sgconf/main.cpp +++ /dev/null @@ -1,465 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Author : Boris Mikhailenko - * Author : Maxim Mamontov - */ - -#include "xml.h" -#include "admins.h" -#include "tariffs.h" -#include "users.h" -#include "services.h" -#include "corps.h" -#include "info.h" - -#include "api_action.h" -#include "options.h" -#include "actions.h" -#include "config.h" - -#include -#include - -#include // getenv -#include // str* - -#include // access -#include // basename - -namespace -{ - -template -struct nullary_function -{ -typedef T result_type; -}; - -template -class binder0 : public nullary_function -{ - public: - binder0(const F & func, const typename F::argument_type & arg) - : m_func(func), m_arg(arg) {} - typename F::result_type operator()() const { return m_func(m_arg); } - private: - F m_func; - typename F::argument_type m_arg; -}; - -template -inline -binder0 bind0(const F & func, const typename F::argument_type & arg) -{ -return binder0(func, arg); -} - -template -class FUNC1_ADAPTER : public std::unary_function -{ - public: - FUNC1_ADAPTER(R (*func)(A)) : m_func(func) {} - const R operator()(A arg) const { return (m_func)(arg); } - private: - R (*m_func)(A); -}; - -template -class METHOD1_ADAPTER : public std::unary_function -{ - public: - METHOD1_ADAPTER(R (C::* func)(A), C & obj) : m_func(func), m_obj(obj) {} - R operator()(A arg) { return (m_obj.*m_func)(arg); } - private: - R (C::* m_func)(A); - C & m_obj; -}; - -template -class CONST_METHOD1_ADAPTER : public std::unary_function -{ - public: - CONST_METHOD1_ADAPTER(R (C::* func)(A) const, C & obj) : m_func(func), m_obj(obj) {} - R operator()(A arg) const { return (m_obj.*m_func)(arg); } - private: - R (C::* m_func)(A) const; - C & m_obj; -}; - -template -FUNC1_ADAPTER Func1Adapt(R (func)(A)) -{ -return FUNC1_ADAPTER(func); -} - -template -METHOD1_ADAPTER Method1Adapt(R (C::* func)(A), C & obj) -{ -return METHOD1_ADAPTER(func, obj); -} - -template -CONST_METHOD1_ADAPTER Method1Adapt(R (C::* func)(A) const, C & obj) -{ -return CONST_METHOD1_ADAPTER(func, obj); -} - -void Version(const std::string & self) -{ -std::cout << self << ", version: 2.0.0.\n"; -} - -void ReadUserConfigFile(SGCONF::OPTION_BLOCK & block) -{ -std::vector paths; -const char * configHome = getenv("XDG_CONFIG_HOME"); -if (configHome == NULL) - { - const char * home = getenv("HOME"); - if (home == NULL) - return; - paths.push_back(std::string(home) + "/.config/sgconf/sgconf.conf"); - paths.push_back(std::string(home) + "/.sgconf/sgconf.conf"); - } -else - paths.push_back(std::string(configHome) + "/sgconf/sgconf.conf"); -for (std::vector::const_iterator it = paths.begin(); it != paths.end(); ++it) - if (access(it->c_str(), R_OK) == 0) - { - block.ParseFile(*it); - return; - } -} - -} // namespace anonymous - -namespace SGCONF -{ - -class CONFIG_ACTION : public ACTION -{ - public: - CONFIG_ACTION(SGCONF::CONFIG & config, - const std::string & paramDescription) - : m_config(config), - m_description(paramDescription) - {} - - virtual ACTION * Clone() const { return new CONFIG_ACTION(*this); } - - virtual std::string ParamDescription() const { return m_description; } - virtual std::string DefaultDescription() const { return ""; } - virtual OPTION_BLOCK & Suboptions() { return m_suboptions; } - virtual PARSER_STATE Parse(int argc, char ** argv, void * /*data*/); - - private: - SGCONF::CONFIG & m_config; - std::string m_description; - OPTION_BLOCK m_suboptions; - - void ParseCredentials(const std::string & credentials); - void ParseHostAndPort(const std::string & hostAndPort); -}; - - -PARSER_STATE CONFIG_ACTION::Parse(int argc, char ** argv, void * /*data*/) -{ -if (argc == 0 || - argv == NULL || - *argv == NULL) - throw ERROR("Missing argument."); -char * pos = strchr(*argv, '@'); -if (pos != NULL) - { - ParseCredentials(std::string(*argv, pos)); - ParseHostAndPort(std::string(pos + 1)); - } -else - { - ParseHostAndPort(std::string(*argv)); - } -return PARSER_STATE(false, --argc, ++argv); -} - -void CONFIG_ACTION::ParseCredentials(const std::string & credentials) -{ -std::string::size_type pos = credentials.find_first_of(':'); -if (pos != std::string::npos) - { - m_config.userName = credentials.substr(0, pos); - m_config.userPass = credentials.substr(pos + 1); - } -else - { - m_config.userName = credentials; - } -} - -void CONFIG_ACTION::ParseHostAndPort(const std::string & hostAndPort) -{ -std::string::size_type pos = hostAndPort.find_first_of(':'); -if (pos != std::string::npos) - { - m_config.server = hostAndPort.substr(0, pos); - uint16_t port = 0; - if (str2x(hostAndPort.substr(pos + 1), port)) - throw ERROR("Invalid port value: '" + hostAndPort.substr(pos + 1) + "'"); - m_config.port = port; - } -else - { - m_config.server = hostAndPort; - } -} - -inline -CONFIG_ACTION * MakeParamAction(SGCONF::CONFIG & config, - const std::string & paramDescription) -{ -return new CONFIG_ACTION(config, paramDescription); -} - -} // namespace SGCONF - -//----------------------------------------------------------------------------- -int main(int argc, char **argv) -{ -std::string self(basename(argv[0])); -SGCONF::CONFIG config; -SGCONF::COMMANDS commands; - -SGCONF::OPTION_BLOCKS blocks; -blocks.Add("General options") - .Add("c", "config", SGCONF::MakeParamAction(config.configFile, std::string("~/.config/stg/sgconf.conf"), ""), "override default config file") - .Add("h", "help", SGCONF::MakeFunc0Action(bind0(Method1Adapt(&SGCONF::OPTION_BLOCKS::Help, blocks), 0)), "\t\tshow this help and exit") - //.Add("help-all", SGCONF::MakeFunc0Action(UsageAll), "\t\tshow full help and exit") - .Add("v", "version", SGCONF::MakeFunc0Action(bind0(Func1Adapt(Version), self)), "\t\tshow version information and exit"); -SGCONF::OPTION_BLOCK & block = blocks.Add("Connection options") - .Add("s", "server", SGCONF::MakeParamAction(config.server, std::string("localhost"), "

"), "\t\thost to connect") - .Add("p", "port", SGCONF::MakeParamAction(config.port, uint16_t(5555), ""), "\t\tport to connect") - .Add("local-address", SGCONF::MakeParamAction(config.localAddress, std::string(""), "
"), "\tlocal address to bind") - .Add("local-port", SGCONF::MakeParamAction(config.localPort, uint16_t(0), ""), "\t\tlocal port to bind") - .Add("u", "username", SGCONF::MakeParamAction(config.userName, std::string("admin"), ""), "\tadministrative login") - .Add("w", "userpass", SGCONF::MakeParamAction(config.userPass, ""), "\tpassword for the administrative login") - .Add("a", "address", SGCONF::MakeParamAction(config, ""), "connection params as a single string in format: :@:"); -blocks.Add("Debug options") - .Add("show-config", SGCONF::MakeParamAction(config.showConfig), "\tshow config and exit"); -SGCONF::AppendXMLOptionBlock(commands, blocks); -SGCONF::AppendServerInfoBlock(commands, blocks); -SGCONF::AppendAdminsOptionBlock(commands, blocks); -SGCONF::AppendTariffsOptionBlock(commands, blocks); -SGCONF::AppendUsersOptionBlock(commands, blocks); -SGCONF::AppendServicesOptionBlock(commands, blocks); -SGCONF::AppendCorpsOptionBlock(commands, blocks); - -SGCONF::PARSER_STATE state(false, argc, argv); - -try -{ -state = blocks.Parse(--argc, ++argv); // Skipping self name -} -catch (const SGCONF::OPTION::ERROR& ex) -{ -std::cerr << ex.what() << "\n"; -return -1; -} - -if (state.stop) - return 0; - -if (state.argc > 0) - { - std::cerr << "Unknown option: '" << *state.argv << "'\n"; - return -1; - } - -try -{ -SGCONF::CONFIG configOverride(config); - -if (config.configFile.empty()) - { - const char * mainConfigFile = "/etc/sgconf/sgconf.conf"; - if (access(mainConfigFile, R_OK) == 0) - block.ParseFile(mainConfigFile); - ReadUserConfigFile(block); - } -else - { - block.ParseFile(config.configFile.data()); - } - -config = configOverride; - -if (!config.showConfig.empty() && config.showConfig.data()) - { - std::cout << config.Serialize() << std::endl; - return 0; - } -return commands.Execute(config) ? 0 : -1; -} -catch (const std::exception& ex) -{ -std::cerr << ex.what() << "\n"; -return -1; -} -} -//----------------------------------------------------------------------------- - -namespace -{ - -/*void UsageTariffs(bool full) -{ -std::cout << "Tariffs management options:\n" - << "\t--get-tariffs\t\t\t\tget a list of tariffs (subsequent options will define what to show)\n"; -if (full) - std::cout << "\t\t--name\t\t\t\tshow tariff's name\n" - << "\t\t--fee\t\t\t\tshow tariff's fee\n" - << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n" - << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n" - << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n"; -std::cout << "\t--get-tariff\t\t\t\tget the information about tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to show\n" - << "\t\t--fee\t\t\t\tshow tariff's fee\n" - << "\t\t--free\t\t\t\tshow tariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost\t\t\tshow tariff's cost of \"freeze\"\n" - << "\t\t--traff-type\t\t\tshow what type of traffix will be accounted by the tariff\n" - << "\t\t--dirs\t\t\t\tshow tarification rules for directions\n\n"; -std::cout << "\t--add-tariff\t\t\t\tadd a new tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to add\n" - << "\t\t--fee \t\t\tstariff's fee\n" - << "\t\t--free \t\t\ttariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost \t\ttariff's cost of \"freeze\"\n" - << "\t\t--traff-type \t\twhat type of traffi will be accounted by the tariff\n" - << "\t\t--times \t\t\tslash-separated list of \"day\" time-spans (in form \"hh:mm-hh:mm\") for each direction\n" - << "\t\t--prices-day-a \t\tslash-separated list of prices for \"day\" traffic before threshold for each direction\n" - << "\t\t--prices-night-a \tslash-separated list of prices for \"night\" traffic before threshold for each direction\n" - << "\t\t--prices-day-b \t\tslash-separated list of prices for \"day\" traffic after threshold for each direction\n" - << "\t\t--prices-night-b \tslash-separated list of prices for \"night\" traffic after threshold for each direction\n" - << "\t\t--single-prices \tslash-separated list of \"single price\" flags for each direction\n" - << "\t\t--no-discounts \t\tslash-separated list of \"no discount\" flags for each direction\n" - << "\t\t--thresholds \tslash-separated list of thresholds (in Mb) for each direction\n\n"; -std::cout << "\t--del-tariff\t\t\t\tdelete an existing tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to delete\n\n"; -std::cout << "\t--chg-tariff\t\t\t\tchange an existing tariff\n"; -if (full) - std::cout << "\t\t--name \t\t\tname of the tariff to change\n" - << "\t\t--fee \t\t\tstariff's fee\n" - << "\t\t--free \t\t\ttariff's prepaid traffic in terms of cost\n" - << "\t\t--passive-cost \t\ttariff's cost of \"freeze\"\n" - << "\t\t--traff-type \t\twhat type of traffix will be accounted by the tariff\n" - << "\t\t--dir \t\t\tnumber of direction data to change\n" - << "\t\t\t--time